API Documentation

Content Objects

Metro Publisher provides several different types of content objects:

  • article
  • event
  • recipe
  • review_album
  • review_book
  • review_location
  • review_product
  • roundup_location

Deprecated as a separate content type as of Metro Publisher 2.8:

Content objects have many attributes in common, such as title, description and content, for example. Please refer to the PUT /{iid}/content/{uuid} resource of Content for the list of common attributes as well as content type specfic attributes.

Goal

Let's assume we have a section as well as a blog in our Metro Publisher instance:

  • section
    • title: Vacations
    • UUID: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
  • blog
    • title: Rome Vacations Blog
    • UUID: bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb

We also have two locations and some images:

  • location 1
    • title: Villa Medici
    • UUID: cccccccc-cccc-cccc-cccc-cccccccccccc
  • location 2
    • title: Teatro Argentina
    • UUID: dddddddd-dddd-dddd-dddd-dddddddddddd
  • image 1
    • title: Villa Medici Wallpaper
    • UUID: ffffffff-ffff-ffff-ffff-cccccccccccc
  • image 2
    • title: Villa Medici Book Cover
    • UUID: ffffffff-ffff-ffff-ffff-dddddddddddd
  • image 3
    • title: Villa Medici CD Cover
    • UUID: ffffffff-ffff-ffff-ffff-eeeeeeeeeeee
  • image 4
    • title: Rome at Night
    • UUID: ffffffff-ffff-ffff-ffff-ffffffffffff
  • image 5
    • title: Spaghetti Carbonara
    • UUID: ffffffff-ffff-ffff-ffff-000000000000

Let's say we want to create some content around a trip to Rome:

  • an article about the trip
  • a blog post created during the trip
  • an event happening in one of the locations (Teatro Argentina)
  • a review of one of the locations (Villa Medici)
  • a review of a CD for a guided tour of the Villa Medici
  • a review of a Villa Medici book, and
  • a review of a product related to the Villa Medici
  • a roundup of locations
  • a recipe

Adding Content Objects

Article

We'll start with an article. The article is just a general text about the experience of taking a trip to Rome. Since it concerns a vacation to Italy, it makes sense to put it into the 'Vacations' section (UUID: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa):

>>> PUT("/123/content/11111111-1111-1111-1111-111111111111",
... {'title': 'My Last Trip to Rome',
...  'urlname': 'my-last-trip-to-rome',
...  'description': 'Last christmas I decided that this year I would finally take that trip to Rome that I had been thinking about for so many years.',
...  'content': "<p>In May, it was time to plan for this year's vacation, ...</p>",
...  'created': '2012-08-12T10:00:00',
...  'modified': '2012-08-12T10:00:00',
...  'content_type': 'article',
...  'state': 'published',
...  'issued': '2012-08-12T10:00:00',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'})
{'url': 'https://api.metropublisher.com/123/content/11111111-1111-1111-1111-111111111111',
 'uuid': '11111111-1111-1111-1111-111111111111'}

Let's have a closer look at the parameters:

title, urlname, content_type

The required parameters for content objects are title, urlname and content_type. Since all content objects are created using the same API resource (PUT /{iid}/content/{uuid}), we must define what type of content object we want to add ('content_type': 'article'). The urlname is part of the URL at which the new article can be accessed on the website and the value for urlname must therefore adhere to certain rules. The urlname must not start with either '@' nor '+' and must not contain a '/'. It's good practice to use the title as a basis for the urlname, so in the example here we've chosen a urlname that is basically the title in all lowercase letters and with the spaces replaced by a dash. The urlname must also be unique within its "part" of the instance, i.e. unique per section (in case of articles and reviews), unique per blog if the object is associated with a blog instead of a section, or unique per their content type (in case of events and videos).

content

An article, or any other content object, does not make much sense without actual text content. The content field of articles, reviews, etc. allows XML-compliant HTML, with restrictions. The field is validated using RelaxNG with the schema files shown in RelaxNG Schema for XML-compliant HTML.

Here's an example of what would happen if we tried to add a new article with the same urlname as the one above and with invalid content:

>>> PUT("/123/content/11111111-1111-1111-1111-222222222222",
... {'title': 'My Last Trip to Rome',
...  'urlname': 'my-last-trip-to-rome',
...  'content': "<p>In May, it was time to plan for this year's <span style='color:red'>vacation</span>, ...</p>",
...  'content_type': 'article',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'})
{'error': 'bad_parameters',
 'error_description': 'One or more of your incoming parameters failed validation, see info for details',
 'error_info': {'content': 'XML does not conform to the RelaxNG schema.',
                'urlname': 'URLName not unique within section.'}}

So, in order to use the Metro Publisher API to add content objects to a Metro Publisher instance, you need to clean up the content value before sending it to the API.

Moving on to the other parameters:

state, issued

A content object can have one of two states: draft or published. An article with the state 'draft' will not be accessible via the public Metro Publisher website. An article with the state 'published' is dependent on the issued date/time of the article, i.e. it will only be publicly available from the issued date/time onwards. The issued date/time is therefore required if the article's state is set to 'published'.

section_uuid

By assigning a section_uuid for the article, we essential put the article "inside" the section 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' ('Vacations').

Blog Content (former Blogentries)

Deprecated since MP 2.10:

With MP 2.10, sections are enhanced to work like blogs. Old blogs will be available until merged to sections manually via the Metro Pulisher Administration Interface.

(also see ChangeLog)

An article or review can be associated with a blog instead of a section, making it part of that blog, i.e. something usually referred to as a blogentry or blog post. So, in order to create such a content object, we create, for example, an article but pass along a blog_uuid instead of a section_uuid:

>>> PUT("/123/content/22222222-2222-2222-2222-222222222222",
... {'title': 'Day 1 - The Hotel',
...  'urlname': 'day-1---the-hotel',
...  'description': 'I made it. Yay!',
...  'content': "<p>Checked into my hotel. Beautiful lobby, but the room is slightly less opulent...</p>",
...  'created': '2012-08-08T10:00:00',
...  'modified': '2012-08-08T10:00:00',
...  'content_type': 'article',
...  'blog_uuid': 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
...  'state': 'published',
...  'issued': '2012-08-08T10:00:00'})
{'url': 'https://api.metropublisher.com/123/content/22222222-2222-2222-2222-222222222222',
 'uuid': '22222222-2222-2222-2222-222222222222'}

Note

We could have also created this as a review instead of an article. See Review for information about a review's additional parameters.

Event

Let's say that during the trip in Rome, we noticed that there will be a special show at "Teatro Argentina" that we'd like to let our website visitors know about in case they happen to be in Rome at the time the show (i.e. event) happens. So we add an event:

>>> PUT("/123/content/33333333-3333-3333-3333-333333333333",
... {'title': 'Birds with skymirrors',
...  'urlname': 'birds-with-skymirrors',
...  'content': "<p><strong>Italian Premier</strong></p><p><em>Lemi Ponifasio // Mau</em></p><p>An elegy to nature and its vitality, its enigma.</p>",
...  'created': '2012-08-08T10:00:00',
...  'modified': '2012-08-08T10:00:00',
...  'content_type': 'event',
...  'location_uuid': 'dddddddd-dddd-dddd-dddd-dddddddddddd',
...  'state': 'published',
...  'issued': '2012-08-08T10:00:00',
...  'website': 'http://teatrodiroma.net',
...  'phone': '(555) 1234',
...  'dtstart': '2012-10-26',
...  'dtend': '2012-10-28',
...  'ical_uid': '33333333-3333-3333-3333-333333333333'})
{'url': 'https://api.metropublisher.com/123/content/33333333-3333-3333-3333-333333333333',
 'uuid': '33333333-3333-3333-3333-333333333333'}

There are a few special event-specific parameters here:

location_uuid

This is the UUID of the location where the event takes place, in this case "Teatro Argentina" which has the UUID 'dddddddd-dddd-dddd-dddd-dddddddddddd' (see Goal above).

dtstart, dtend

An event must have a start and end date or date/time. In Metro Publisher both dtstart and dtend must have the same type, i.e. either both are a date or both are a date/time.

ical_uid

This parameter is a unique identifier as defined in RFC 5545. Metro Publisher uses the event's UUID but it can be anything conforming to the RFC specification.

website, phone

The website is the website of the event. The phone is the contact phone number for this event.

Recurring Events

We created the event above as an event happening from the 26th to the 28th October. However, it isn't really a three-day event but an event that happens on three separate occasions. According to the theater's website, the event happens on:

    1. October 2012 at 9pm
    1. October 2012 at 7pm
    1. October 2012 at 5pm

So, let's correct the event and make it a recurring event, i.e. one event with three occurrences.

>>> PUT("/123/content/33333333-3333-3333-3333-333333333333",
... {'title': 'Birds with skymirrors',
...  'urlname': 'birds-with-skymirrors',
...  'content': "<p><strong>Italian Premier</strong></p><p><em>Lemi Ponifasio // Mau</em></p><p>An elegy to nature and its vitality, its enigma.</p>",
...  'created': '2012-08-08T10:00:00',
...  'modified': '2012-08-08T10:00:00',
...  'content_type': 'event',
...  'location_uuid': 'dddddddd-dddd-dddd-dddd-dddddddddddd',
...  'state': 'published',
...  'issued': '2012-08-08T10:00:00',
...  'url': 'http://teatrodiroma.net',
...  'dtstart': '2012-10-26T21:00:00',
...  'dtend': '2012-10-26T23:30:00',
...  'rdates': ['2012-10-27T19:00:00', '2012-10-28T17:00:00'],
...  'ical_uid': '33333333-3333-3333-3333-333333333333'})
{'url': 'https://api.metropublisher.com/123/content/33333333-3333-3333-3333-333333333333',
 'uuid': '33333333-3333-3333-3333-333333333333'}

The differences between the PUT request for the non-recurring event and the recurring event are:

  • dtstart and dtend define the start and end date/time of the first occurrence:
    • dtstart: 26. October 2012, 9pm
    • dtend: 26. October 2012, 11:30pm
  • the new parameter rdates defines the start date/times of the other occurrences:
      1. October 2012, 7pm
      1. October 2012, 5pm

Recurrence Rule

If the three occurrences all had the same start time, we could have defined a recurrence rule for the event. In that case the event would happen on a daily basis either for three occurrences or until October 28th, 2012:

>>> PUT("/123/content/33333333-3333-3333-3333-333333333333",
... {'title': 'Birds with skymirrors',
...  'urlname': 'birds-with-skymirrors',
...  'content': "<p><strong>Italian Premier</strong></p><p><em>Lemi Ponifasio // Mau</em></p><p>An elegy to nature and its vitality, its enigma.</p>",
...  'created': '2012-08-08T10:00:00',
...  'modified': '2012-08-08T10:00:00',
...  'content_type': 'event',
...  'location_uuid': 'dddddddd-dddd-dddd-dddd-dddddddddddd',
...  'state': 'published',
...  'issued': '2012-08-08T10:00:00',
...  'url': 'http://teatrodiroma.net',
...  'dtstart': '2012-10-26T21:00:00',
...  'dtend': '2012-10-26T23:30:00',
...  'rrule': {'freq': 'DAILY',
...            'interval': 1,
...            'count': 3},
...  'ical_uid': '33333333-3333-3333-3333-333333333333'})
{'url': 'https://api.metropublisher.com/123/content/33333333-3333-3333-3333-333333333333',
 'uuid': '33333333-3333-3333-3333-333333333333'}

For a recurring event that can be defined by a recurrence rule, we don't use the rdates parameter but instead use the rrule parameter.

freq, interval

The freq parameter defines how the interval parameter is interpreted. Here it means: every 1 day.

count

The count parameter specifies how many occurrences there are. Here it means: the event occurs 3 times.

Note

The parameters rrule and rdates are not mutually exclusive. You can have both a recurrence rule as well as additional occurrences that fall outside the rule.

Note

For more information regarding the recurrence rule, please refer to RFC 5545.

Review

As of version 2.11, Metro Publisher supports four types of reviews:

  • album (New in 2.11)
  • book (New in 2.11)
  • location
  • product (New in 2.11)

Album Review

Let's say that there is a guided tour on CD available for the 'Villa Medici'. For this we can add an album review (content_type: 'review_album') with some information concerning the CD, such as its title, and cover image:

>>> PUT("/123/content/44444444-4444-4444-4444-111111111111",
... {'title': 'Villa Medici CD',
...  'urlname': 'villa-medici-cd',
...  'description': 'The Villa Medici offers guided tours on CD.',
...  'content': "",
...  'created': '2012-08-10T10:00:00',
...  'modified': '2012-08-10T10:00:00',
...  'content_type': 'review_album',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-bbbbbbbbbbbb',
...  'rating': '3',
...  'state': 'published',
...  'issued': '2012-08-07T10:00:00',
...  'album_title': 'Villa Medici - The Guided Tour - CD',
...  'album_issued': 'October 2012',
...  'album_buy_urls': [{'url': 'http://www.villamedici.it/tour-cd.html',
...                      'link_text': 'Buy on Villa Medici Website'}],
...  'album_image_uuid': 'ffffffff-ffff-ffff-ffff-eeeeeeeeeeee',
...  'album_provider_urls': ['https://itunes.apple.com/de/album/medici/id266042361?l=en']})
{'url': 'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-111111111111',
 'uuid': '44444444-4444-4444-4444-111111111111'}

rating

The rating may be a value between 0 and 5, in .5 increments, i.e. 0, 0.5, 1, 1.5, etc.

album_title

The title of the album that is being reviewed.

album_issued

The release date of the album. This can be a freetext, such as 'October 2014', or a date, such as '2014-10-05'.

album_provider_urls

The album_provider_urls is a list of urls that link to pages where the album can be bought. Metro Publisher currently supports Amazon and iTunes links.

album_buy_urls

The album_buy_urls parameter can be used to provide a list of links to pages where the album can be bought. This is only needed for links that are not natively supported by Metro Publisher (see album_provider_urls).

album_image_uuid

This is the UUID to the album cover image. The image must already exist in the Metro Publisher instance.

Book Review

There are also books available about the Medici and their villas. To add a book review for one of these books, we add a review with the content_type 'review_book' and some additional information about the book, such as its title aned ISBN:

>>> PUT("/123/content/44444444-4444-4444-4444-222222222222",
... {'title': 'Villa Medici Book',
...  'urlname': 'villa-medici-book',
...  'description': 'This title is a superbly illustrated guide to the entire range of Medici Villas open to the public in Florence and Tuscany.',
...  'content': "",
...  'created': '2012-08-10T10:00:00',
...  'modified': '2012-08-10T10:00:00',
...  'content_type': 'review_book',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-bbbbbbbbbbbb',
...  'rating': '3',
...  'state': 'published',
...  'issued': '2012-08-11T10:00:00',
...  'book_title': 'The Medici Villas: Complete Guide',
...  'book_isbn': '978-8809766327',
...  'book_issued': '2011-10-01',
...  'book_buy_urls': [{'url': 'http://www.villamedici.it/books.html',
...                     'link_text': 'Buy on Villa Medici Website'}],
...  'book_image_uuid': 'ffffffff-ffff-ffff-ffff-dddddddddddd',
...  'book_provider_urls': ['http://www.amazon.com/dp/8809766326/']})
{'url': 'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-222222222222',
 'uuid': '44444444-4444-4444-4444-222222222222'}

rating

The rating may be a value between 0 and 5, in .5 increments, i.e. 0, 0.5, 1, 1.5, etc.

book_title

The title of the book that is being reviewed.

book_isbn

The ISBN of the book. This can be either an ISBN-10 or an ISBN-13.

book_issued

The publish date of the book. This can be a freetext, such as 'October 2014', or a date, such as '2014-10-05'.

book_provider_urls

The book_provider_urls is a list of urls that link to pages where the book can be bought. Metro Publisher currently supports Amazon and iTunes links.

book_buy_urls

The book_buy_urls parameter can be used to provide a list of links to pages where the book can be bought. This is only needed for links that are not natively supported by Metro Publisher (see book_provider_urls).

book_image_uuid

This is the UUID to the book cover image. The image must already exist in the Metro Publisher instance.

Movie Review

Besides the book, there is also a DVD called "Villa Medici DVD". Let's also create a review for this movie (content_type: 'review_movie'):

>>> PUT("/123/content/44444444-4444-4444-4444-555555555555",
... {'title': 'Villa Medici DVD',
...  'urlname': 'villa-medici-dvd',
...  'description': '',
...  'content': "",
...  'created': '2012-08-10T10:00:00',
...  'modified': '2012-08-10T10:00:00',
...  'content_type': 'review_movie',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-bbbbbbbbbbbb',
...  'rating': '3.5',
...  'state': 'published',
...  'issued': '2012-08-13T10:00:00',
...  'movie_title': 'Villa Medici - The Guided Tour - DVD',
...  'movie_duration': 96,
...  'movie_issued': 'May 29, 2011',
...  'movie_buy_urls': [{'url': 'http://www.villamedici.it/movies.html',
...                        'link_text': 'Buy on Villa Medici Website'}],
...  'movie_image_uuid': 'ffffffff-ffff-ffff-ffff-cccccccccccc',
...  'movie_provider_urls': ['http://www.amazon.com/dp/B00536M3YC/']})
{'url': 'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-555555555555',
 'uuid': '44444444-4444-4444-4444-555555555555'}

rating

The rating may be a value between 0 and 5, in .5 increments, i.e. 0, 0.5, 1, 1.5, etc.

movie_title

The title of the movie that is being reviewed.

movie_duratin

This is the length of the movie, in minutes.

movie_issued

The publish date of the movie. This can be a freetext, such as 'October 2014', or a date, such as '2014-10-05'.

movie_provider_urls

The movie_provider_urls is a list of urls that link to pages where the movie can be bought. Metro Publisher currently supports Amazon and iTunes links.

movie_buy_urls

The movie_buy_urls parameter can be used to provide a list of links to pages where the movie can be bought. This is only needed for links that are not natively supported by Metro Publisher (see movie_provider_urls).

movie_image_uuid

This is the UUID to the movie image. The image must already exist in the Metro Publisher instance.

Location Review

The next content object we want to add is a review of the "Villa Medici" (a location), or more specifically of the guided tour they offer. Reviews may concern a location, as in our example. Therefore, we can connect the review to the location "Villa Medici" by passing its location_uuid (UUID: cccccccc-cccc-cccc-cccc-cccccccccccc) and specifying the content_type to be 'review_location':

>>> PUT("/123/content/44444444-4444-4444-4444-444444444444",
... {'title': 'Villa Medici - The Guided Tour',
...  'urlname': 'villa-medici--the-guided-tour',
...  'description': 'The Villa Medici offers guided tours in three differenct languages.',
...  'content': "<p>Beautiful grounds and wonderful architecture. That's what you will see when you take a guided tour of the Villa Medici...</p>",
...  'created': '2012-08-10T10:00:00',
...  'modified': '2012-08-10T10:00:00',
...  'content_type': 'review_location',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
...  'location_uuid': 'cccccccc-cccc-cccc-cccc-cccccccccccc',
...  'rating': '4.5',
...  'state': 'published',
...  'issued': '2012-08-10T10:00:00'})
{'url': 'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444',
 'uuid': '44444444-4444-4444-4444-444444444444'}

rating

The rating may be a value between 0 and 5, in .5 increments, i.e. 0, 0.5, 1, 1.5, etc.

location_uuid

The UUID of the location that is being reviewed. This location must already exist in the Metro Publisher instance.

Product Review

There is wallpaper available that is called "Wallcovering Villa Medici". We now want to add a review for this product (content_type: 'review_product'):

>>> PUT("/123/content/44444444-4444-4444-4444-333333333333",
... {'title': 'Wallcovering Villa Medici',
...  'urlname': 'villa-medici-wallpaper',
...  'description': 'Live like the Medicis, with wallpaper.',
...  'content': "",
...  'created': '2012-08-10T10:00:00',
...  'modified': '2012-08-10T10:00:00',
...  'content_type': 'review_product',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-bbbbbbbbbbbb',
...  'rating': '3',
...  'state': 'published',
...  'issued': '2012-08-13T10:00:00',
...  'product_title': 'Wallpaper Seabrook Wallcovering Villa Medici VM50209',
...  'product_issued': 'May 29, 2011',
...  'product_buy_urls': [{'url': 'http://www.villamedici.it/products.html',
...                        'link_text': 'Buy on Villa Medici Website'}],
...  'product_image_uuid': 'ffffffff-ffff-ffff-ffff-cccccccccccc',
...  'product_provider_urls': ['http://www.amazon.com/dp/B00536M3YC/']})
{'url': 'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-333333333333',
 'uuid': '44444444-4444-4444-4444-333333333333'}

rating

The rating may be a value between 0 and 5, in .5 increments, i.e. 0, 0.5, 1, 1.5, etc.

product_title

The title of the product that is being reviewed.

product_issued

The publish date of the product. This can be a freetext, such as 'October 2014', or a date, such as '2014-10-05'.

product_provider_urls

The product_provider_urls is a list of urls that link to pages where the product can be bought. Metro Publisher currently supports Amazon and iTunes links.

product_buy_urls

The product_buy_urls parameter can be used to provide a list of links to pages where the product can be bought. This is only needed for links that are not natively supported by Metro Publisher (see product_provider_urls).

product_image_uuid

This is the UUID to the product image. The image must already exist in the Metro Publisher instance.

Location Roundup

A roundup is a collection of things. As of 2.11, Metro Publisher supports location roundups. On the public website, the location roundup will show the locations in a list as well as a map with markers for the locations.

>>> PUT("/123/content/55555555-5555-5555-5555-555555555555",
... {'title': 'Places to See',
...  'urlname': 'places-to-see',
...  'created': '2012-08-14T10:00:00',
...  'modified': '2012-08-14T10:00:00',
...  'content_type': 'roundup_location',
...  'state': 'published',
...  'issued': '2012-08-15T10:00:00',
...  'roundup_location_hide_map': False,
...  'roundup_locations': [{'location_uuid': 'cccccccc-cccc-cccc-cccc-cccccccccccc'},
...                        {'location_uuid': 'dddddddd-dddd-dddd-dddd-dddddddddddd',
...                         'description': '<p>Great theater!</p>'}],
...  'roundup_location_tour_type': 'drive',
...  'roundup_numbering': 'ascending'})
{'url': 'https://api.metropublisher.com/123/content/55555555-5555-5555-5555-555555555555',
 'uuid': '55555555-5555-5555-5555-555555555555'}

roundup_locations

This is a list of the locations for this roundup. Each location information consists of the location_uuid (must already exist in the Metro Publisher instance) and optionally an override description and an override image. If no overrides are set for a location, the description and image of the location are used.

roundup_location_tour_type

If the location roundup has a tour type, the public page of the roundup uses the Google Directions Service to show directions from one location to the next location in the list. The tour type defines the default type for the directions: drive, cycle or walk.

Content Roundup

Metro Publisher also supports content roundups, which may contain a mix of articles, reviews, roundups and events.

>>> PUT("/123/content/66666666-6666-6666-6666-666666666666",
... {'title': 'The Medici',
...  'urlname': 'the-medici',
...  'created': '2012-08-14T10:00:00',
...  'modified': '2012-08-14T10:00:00',
...  'content_type': 'roundup_content',
...  'state': 'published',
...  'issued': '2012-08-15T10:00:00',
...  'roundup_content_targets': [{'target_uuid': '44444444-4444-4444-4444-444444444444'},
...                              {'target_uuid': '44444444-4444-4444-4444-222222222222'},
...                              {'target_uuid': '44444444-4444-4444-4444-111111111111'},
...                              {'target_uuid': '44444444-4444-4444-4444-333333333333'}],
...  'roundup_numbering': 'ascending'})
{'url': 'https://api.metropublisher.com/123/content/66666666-6666-6666-6666-666666666666',
 'uuid': '66666666-6666-6666-6666-666666666666'}

roundup_content_targets

This is a list of the content objects for this roundup. Each content object must already exist in the Metro Publisher instance.

Recipe

Next, we want to add a recipe for Spaghetti Carbonara:

>>> PUT("/123/content/88888888-8888-8888-8888-888888888888",
... {'title': 'Spaghetti Carbonara',
...  'urlname': 'spaghetti-carbonara',
...  'created': '2020-08-14T10:00:00',
...  'modified': '2020-08-14T10:00:00',
...  'content_type': 'recipe',
...  'content': '<p>Cook pasta al dente in saltwater. Mix salt, pepper and nutmeg...</p>',
...  'state': 'published',
...  'issued': '2020-08-15T10:00:00',
...  'recipe_prep_time': 5,
...  'recipe_cook_time': 15,
...  'recipe_yield': '4 servings',
...  'recipe_image_uuid': 'ffffffff-ffff-ffff-ffff-000000000000',
...  'recipe_ingredients': [{'amount': 400, 'unit': 'g', 'ingredient': 'Spaghetti'},
...                         {'amount': 200, 'unit': 'g', 'ingredient': 'ham, raw'},
...                         {'amount': 4, 'ingredient': 'egg yolk'},
...                         {'amount': 50, 'unit': 'g', 'ingredient': 'butter'},
...                         {'ingredient': 'salt and pepper'},
...                         {'amount': 1, 'unit': 'pinch', 'ingredient': 'nutmeg'},
...                         {'amount': 70, 'unit': 'g', 'ingredient': 'flour'}]})
{'url': 'https://api.metropublisher.com/123/content/88888888-8888-8888-8888-888888888888',
 'uuid': '88888888-8888-8888-8888-888888888888'}

recipe_prep_time

This is the preparation time for the recipe, given in minutes.

recipe_cook_time

This is the cooking time for the recipe, given in minutes.

recipe_yield

This is a freetext field for the recipe yield, e.g. '1 loaf' or '4 servings'.

recipe_ingredients

This is a list of the recipe ingredients. Each ingredient consists of an optional amount, an optional unit and a required ingredient name.

recipe_image_uuid

This is the UUID to the main recipe image. The image must already exist in the Metro Publisher instance.

Retrieving a List of Content

Now that we've added the various content objects, we can retrieve the list of available content using the GET /{iid}/content resource. We can specify a number of fields to retrieve for each content object, such as the title and issued date of the object as well as the API url to the object:

>>> GET("/123/content?fields=title-issued-url")
{'items': [['Birds with skymirrors',
            '2012-08-08T10:00:00',
            'https://api.metropublisher.com/123/content/33333333-3333-3333-3333-333333333333'],
           ['Day 1 - The Hotel',
            '2012-08-08T10:00:00',
            'https://api.metropublisher.com/123/content/22222222-2222-2222-2222-222222222222'],
           ['My Last Trip to Rome',
            '2012-08-12T10:00:00',
            'https://api.metropublisher.com/123/content/11111111-1111-1111-1111-111111111111'],
           ['Places to See',
            '2012-08-15T10:00:00',
            'https://api.metropublisher.com/123/content/55555555-5555-5555-5555-555555555555'],
           ['Spaghetti Carbonara',
            '2020-08-15T10:00:00',
            'https://api.metropublisher.com/123/content/88888888-8888-8888-8888-888888888888'],
           ['The Medici',
            '2012-08-15T10:00:00',
            'https://api.metropublisher.com/123/content/66666666-6666-6666-6666-666666666666'],
           ['Villa Medici - The Guided Tour',
            '2012-08-10T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444'],
           ['Villa Medici Book',
            '2012-08-11T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-222222222222'],
           ['Villa Medici CD',
            '2012-08-07T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-111111111111'],
           ['Villa Medici DVD',
            '2012-08-13T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-555555555555'],
           ['Wallcovering Villa Medici',
            '2012-08-13T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-333333333333']]}

Filters

There are various filters we can apply to retrieve specific objects. Here are some examples:

by content type

By default, GET /{iid}/content returns all types of content. The list, however, can be filtered by type(s) of content, so we can, for example, only retrieve reviews like this:

>>> GET("/123/content?fields=title-issued-url&ctypes=reviews")
{'items': [['Villa Medici - The Guided Tour',
            '2012-08-10T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444'],
           ['Villa Medici Book',
            '2012-08-11T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-222222222222'],
           ['Villa Medici CD',
            '2012-08-07T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-111111111111'],
           ['Villa Medici DVD',
            '2012-08-13T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-555555555555'],
           ['Wallcovering Villa Medici',
            '2012-08-13T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-333333333333']]}

Or we can get specific types, for example all articles, location reviews and location roundups:

>>> GET("/123/content?fields=title-issued-url&ctypes=articles-reviews_location-roundups_location")
{'items': [['My Last Trip to Rome',
            '2012-08-12T10:00:00',
            'https://api.metropublisher.com/123/content/11111111-1111-1111-1111-111111111111'],
           ['Places to See',
            '2012-08-15T10:00:00',
            'https://api.metropublisher.com/123/content/55555555-5555-5555-5555-555555555555'],
           ['Villa Medici - The Guided Tour',
            '2012-08-10T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444']]}

by section(s)

For example, if we want to find all content assigned to the section 'Vacations' with the UUID 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' ordered by their issued date in descending order, i.e latest first, we send the following request:

>>> GET("/123/content?fields=title-issued-url&sections=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&order=issued.desc")
{'items': [['My Last Trip to Rome',
            '2012-08-12T10:00:00',
            'https://api.metropublisher.com/123/content/11111111-1111-1111-1111-111111111111'],
           ['Villa Medici - The Guided Tour',
            '2012-08-10T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444']]}

Note

The sections parameter may contain more than just one section UUID.

by issued date

Another filter we might want to apply could be the issued filter. With this filter, we can retrieve objects issued within a certain period of time. The period of time can be open-ended, i.e. we could filter for objects issued before a certain date/time or after a certain date/time, but we can also find objects issued between a starting date/time and an ending date/time:

  • open-ended issued filter (note the "_" right before/right after the date):
    • issued date before a certain date/time: "issued=_2012-08-10"
    • issued date after a certain date/time: "issued=2012-08-10_"
  • specific period of time:
    • "issued=2012-08-09_2012-08-11"

Here's an example:

>>> GET("/123/content?fields=title-issued-url&issued=2012-08-09_2012-08-12T12:00:00&order=issued.desc")
{'items': [['My Last Trip to Rome',
            '2012-08-12T10:00:00',
            'https://api.metropublisher.com/123/content/11111111-1111-1111-1111-111111111111'],
           ['Villa Medici Book',
            '2012-08-11T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-222222222222'],
           ['Villa Medici - The Guided Tour',
            '2012-08-10T10:00:00',
            'https://api.metropublisher.com/123/content/44444444-4444-4444-4444-444444444444']]}

The issued filter accepts either a date or a date/time.

by blog(s)

Deprecated since MP 2.10:

With MP 2.10, sections are enhanced to work like blogs. Old blogs will be available until merged to sections manually via the Metro Pulisher Administration Interface.

(also see ChangeLog)

The GET /{iid}/content resource can also be used to retrieve the content associated with a specific blog. We added one article earlier that resides inside the 'Rome Vacation Blog' (UUID: 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'). Using the blogs filter, we can retrieve this particular blog's content like this:

>>> GET("/123/content?fields=title-issued-url&blogs=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb&order=issued.desc")
{'items': [['Day 1 - The Hotel',
            '2012-08-08T10:00:00',
            'https://api.metropublisher.com/123/content/22222222-2222-2222-2222-222222222222']]}

This call will return all articles and reviews associated with this blog. You can use the ctypes parameter to filter either by articles or reviews.

The blogs filter, like the sections filter, may contain a list of blog uuids.

Retrieving Content Information

To retrieve information about a specific content object, we simply send a GET request to the content object's API url (/{iid}/content/{uuid}):

>>> GET("/123/content/11111111-1111-1111-1111-111111111111")
{'blog_uuid': None,
 'canonical_url': None,
 'content': "<p>In May, it was time to plan for this year's vacation, ...</p>",
 'content_type': 'article',
 'created': '2012-08-12T10:00:00',
 'description': 'Last christmas I decided that this year I would finally take that trip to Rome that I had been thinking about for so many years.',
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2012-08-12T10:00:00',
 'meta_description': None,
 'meta_title': None,
 'modified': '2012-08-12T10:00:00',
 'perma_url_path': None,
 'print_description': None,
 'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'My Last Trip to Rome',
 'urlname': 'my-last-trip-to-rome',
 'uuid': '11111111-1111-1111-1111-111111111111',
 'video_uuid': None}

The returned values differ depending on the type of object. For an album review, for example, the returned data contains album_* information:

>>> GET("/123/content/44444444-4444-4444-4444-111111111111")
{'album_buy_link_text': 'Buy on Villa Medici Website',
 'album_buy_url': 'http://www.villamedici.it/tour-cd.html',
 'album_buy_urls': [{'link_text': 'Buy on Villa Medici Website',
                     'url': 'http://www.villamedici.it/tour-cd.html'}],
 'album_image_url': 'https://api.metropublisher.com/123/files/ffffffff-ffff-ffff-ffff-eeeeeeeeeeee',
 'album_issued': 'October 2012',
 'album_provider_urls': ['https://itunes.apple.com/de/album/medici/id266042361?l=en'],
 'album_title': 'Villa Medici - The Guided Tour - CD',
 'canonical_url': None,
 'content': None,
 'content_type': 'review_album',
 'created': '2012-08-10T10:00:00',
 'description': 'The Villa Medici offers guided tours on CD.',
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2012-08-07T10:00:00',
 'meta_description': None,
 'meta_title': None,
 'modified': '2012-08-10T10:00:00',
 'perma_url_path': None,
 'print_description': None,
 'rating': 3,
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'Villa Medici CD',
 'urlname': 'villa-medici-cd',
 'uuid': '44444444-4444-4444-4444-111111111111'}

Information returned for a location roundup:

>>> GET("/123/content/55555555-5555-5555-5555-555555555555")
{'canonical_url': None,
 'content': None,
 'content_type': 'roundup_location',
 'created': '2012-08-14T10:00:00',
 'description': None,
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2012-08-15T10:00:00',
 'meta_description': None,
 'meta_title': None,
 'modified': '2012-08-14T10:00:00',
 'perma_url_path': None,
 'print_description': None,
 'roundup_location_hide_map': False,
 'roundup_location_tour_type': 'drive',
 'roundup_locations': [{'description': None,
                        'image_url': None,
                        'location_uuid': 'cccccccc-cccc-cccc-cccc-cccccccccccc',
                        'title': None},
                       {'description': '<p>Great theater!</p>',
                        'image_url': None,
                        'location_uuid': 'dddddddd-dddd-dddd-dddd-dddddddddddd',
                        'title': None}],
 'roundup_numbering': 'ascending',
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'Places to See',
 'urlname': 'places-to-see',
 'uuid': '55555555-5555-5555-5555-555555555555'}

Information returned for a recipe:

>>> GET("/123/content/88888888-8888-8888-8888-888888888888")
{'canonical_url': None,
 'content': '<p>Cook pasta al dente in saltwater. Mix salt, pepper and nutmeg...</p>',
 'content_type': 'recipe',
 'created': '2020-08-14T10:00:00',
 'description': None,
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2020-08-15T10:00:00',
 'meta_description': None,
 'meta_title': None,
 'modified': '2020-08-14T10:00:00',
 'perma_url_path': None,
 'print_description': None,
 'recipe_cook_time': 15,
 'recipe_image_url': 'https://api.metropublisher.com/123/files/ffffffff-ffff-ffff-ffff-000000000000',
 'recipe_ingredients': [{'amount': 400.0,
                         'ingredient': 'Spaghetti',
                         'unit': 'g'},
                        {'amount': 200.0,
                         'ingredient': 'ham, raw',
                         'unit': 'g'},
                        {'amount': 4.0,
                         'ingredient': 'egg yolk',
                         'unit': None},
                        {'amount': 50.0, 'ingredient': 'butter', 'unit': 'g'},
                        {'amount': None,
                         'ingredient': 'salt and pepper',
                         'unit': None},
                        {'amount': 1.0,
                         'ingredient': 'nutmeg',
                         'unit': 'pinch'},
                        {'amount': 70.0, 'ingredient': 'flour', 'unit': 'g'}],
 'recipe_prep_time': 5,
 'recipe_yield': '4 servings',
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'Spaghetti Carbonara',
 'urlname': 'spaghetti-carbonara',
 'uuid': '88888888-8888-8888-8888-888888888888'}

Converting Content Types

Warning

Converting content objects should not be done lightly. In most cases you will lose information that you cannot get back. For example, if you change an event to an article, you lose all event-specific information, such as start/end date/time, occurrences, etc.

Let's say we created an article but later decide that the article is actually a review of a location. We can change the content type by sending a new PUT request to the object's API url (/{iid}/content/{uuid}) with the corrected content_type as well as any parameters that the new content type requires/allows.

Here's the original article:

>>> GET("/123/content/77777777-7777-7777-7777-777777777777")
{'blog_uuid': None,
 'canonical_url': None,
 'content': '<p>Had a wonderful time last evening at this little Italian restaurant around the corner from my hotel...</p>',
 'content_type': 'article',
 'created': '2012-08-13T08:00:00',
 'description': None,
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2012-08-13T08:00:00',
 'meta_description': None,
 'meta_title': None,
 'modified': '2012-08-13T08:00:00',
 'perma_url_path': None,
 'print_description': None,
 'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'Great Food, Great Wine, Great Atmosphere',
 'urlname': 'great-food-great-wine-great-atmosphere',
 'uuid': '77777777-7777-7777-7777-777777777777',
 'video_uuid': None}

To convert this to a location review, we need to let the system know that the content_type is now 'review_location'. Location reviews can have a location connected to them. Let's say the system already contains the location to which we want to connect the review (the location's UUID is 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'). Another attribute of a review is the rating.

With the following PUT request, we convert the article to a review, assign a location and specify a rating:

>>> PUT("/123/content/77777777-7777-7777-7777-777777777777",
... {'title': 'Great Food, Great Wine, Great Atmosphere',
...  'urlname': 'great-food-great-wine-great-atmosphere',
...  'content': "<p>Had a wonderful time last evening at this little Italian restaurant around the corner from my hotel...</p>",
...  'created': '2012-08-13T08:00:00',
...  'modified': '2012-08-13T08:00:00',
...  'content_type': 'review_location',
...  'location_uuid': 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
...  'rating': '4.5',
...  'state': 'published',
...  'issued': '2012-08-13T08:00:00',
...  'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'})
{'url': 'https://api.metropublisher.com/123/content/77777777-7777-7777-7777-777777777777',
 'uuid': '77777777-7777-7777-7777-777777777777'}

Looking at the information of the content object now, we see that the changes have been made:

>>> GET("/123/content/77777777-7777-7777-7777-777777777777")
{'blog_uuid': None,
 'canonical_url': None,
 'content': '<p>Had a wonderful time last evening at this little Italian restaurant around the corner from my hotel...</p>',
 'content_type': 'review_location',
 'created': '2012-08-13T08:00:00',
 'description': None,
 'evergreen': False,
 'feature_image_alttext': None,
 'feature_image_caption': None,
 'feature_image_url': None,
 'feature_thumb_url': None,
 'header_image_url': None,
 'issued': '2012-08-13T08:00:00',
 'location_uuid': 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
 'meta_description': None,
 'meta_title': None,
 'modified': '2012-08-13T08:00:00',
 'perma_url_path': None,
 'print_description': None,
 'rating': 4.5,
 'section_uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
 'state': 'published',
 'sub_title': None,
 'teaser_image_url': None,
 'title': 'Great Food, Great Wine, Great Atmosphere',
 'urlname': 'great-food-great-wine-great-atmosphere',
 'uuid': '77777777-7777-7777-7777-777777777777',
 'video_uuid': None}

Consideration When Migrating Content

When migrating content into a Metro Publisher instance, one thing you may need to consider is that the content may have already acquired a significant amount of social media / search engine recognition, e.g. Facebook Like/Share count.

Scenario

A website is moved from a different CMS to Metro Publisher. In the old CMS, the article My Article had the url:

During the migration from the old CMS to Metro Publisher, the article was placed into a section called 'Our Articles' with the URLName 'our-articles'. In Metro Publisher, the article's url is now:

Problem

The article's Facebook Like/Share count, for example, is associated with the url:

Now that the article was migrated, its url is different. Facebook does not recognize it is the same article, so the connection between the article and the Like/Share count on Facebook is lost.

Solution

In order to make sure that the article retains its social media and search engine recognition, we can set the permanent url path for the article to the path it used to have in the old CMS:

>>> PUT("/123/content/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
... {'title': 'My Article',
...  'urlname': 'my-article',
...  'content': "<p>The content of my article...</p>",
...  'created': '2012-08-13T08:00:00',
...  'modified': '2012-08-13T08:00:00',
...  'content_type': 'article',
...  'state': 'published',
...  'issued': '2012-08-13T08:00:00',
...  'perma_url_path': '/oldsystempath/my-article.html'})
{'url': 'https://api.metropublisher.com/123/content/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
 'uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}

Setting a perma_url_path means that on rendering the article, this path is used to construct the article's url for services that don't follow 301 redirects like "Facebook Likes" or "Add This".

If no perma_url_path is set for a content object, Metro Publisher automatically generates a permanent url based on the content object's UUID, independent on its public url.

Note

The attribute perma_url_path of a content object should only be used if:

  • you migrate content from an existing website and the content's url changes due to the migration, and
  • the content has already acquired significant social media and/or search engine recognition on the old website.

Warning

Changing the perma_url_path may result in the loss of social media and search engine recognition of a specific content object.