User guide - HearstCorp/rover-wiki GitHub Wiki

API design

The API is based on RESTful principles - It has resource-oriented endpoints with a predictable behavior, uses appropriate HTTP verbs for each action, and uses HTTP response codes to indicate API errors.

Access to the API is over HTTPS only. All data is sent and received as JSON.

Authentication

See Authentication

Versions

The current version of the API is v2. Rover uses namespace versioning which means that all resources are prepended with a /:version/ path.

Seeding data

Seed data can be loaded via the loadalldata command. E.g: ./manage.py loadalldata.
This is a thin wrapper around calling ./manage.py loaddata <fixture> for each fixture file.

Response format

The response format of the API is inspired by json:api

List view

Request

GET https://{domain}/v2/tags

Response

HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, POST, HEAD, OPTIONS
{
    "meta": {
        "count": 215
    },
    "data": [
        {
            "id": "014c73f2-e430-427b-950e-c6879d0cbdee",
            "site": "7681d1b7-64f6-4947-8e6c-90f0f15818fb",
            "name": "Entertainment",
            "slug": "entertainment",
            "metadata": {
                "featured": true
            },
            "status": 3,
            "display_type": "3d8bf20f-59fa-4d0a-8d75-46d66e1d0dbc",
            "tag_type": "ebb28c67-8b0d-4824-8825-9557ca96c7cc"
        },
        {
            "id": "02129898-8f9b-4b1e-991b-f0f44ab2fd1c",
            "site": "7681d1b7-64f6-4947-8e6c-90f0f15818fb",
            "name": "News",
            "slug": "news",
            "metadata": {},
            "status": 3,
            "display_type": "3d8bf20f-59fa-4d0a-8d75-46d66e1d0dbc",
            "tag_type": "ebb28c67-8b0d-4824-8825-9557ca96c7cc"
        },
        ...
    ],
    "links": {
        "prev": null,
        "next": "http://server.com/v2/tags?page=2"
    }
}

The response contains the following objects:

Object Description
data the resource collection
links the links to previous and next page in the pagination
meta response metadata, currently contains total resource count for the request

Detail view

Request

GET https://{domain}/v2/tags/014c73f2-e430-427b-950e-c6879d0cbdee

Response

HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
{
    "data": {
        "id": 014c73f2-e430-427b-950e-c6879d0cbdee,
        "site": "7681d1b7-64f6-4947-8e6c-90f0f15818fb",
        "name": "News",
        "slug": "news",
        "metadata": {},
        "status": 2,
        "display_type": "3d8bf20f-59fa-4d0a-8d75-46d66e1d0dbc",
        "tag_type": "ebb28c67-8b0d-4824-8825-9557ca96c7cc"
    }
}

The response encapsulates the resource in a data object

Errors

Error responses are encapsulated in an errors array and provide various amount of information based on error type

Examples

Requested resource not found

{
    "errors": [
        {
            "status": "404",
            "title": "Not found."
        }
    ]
}

Required fields missing on resource creation

{
    "errors": [
        {
            "status": "400",
            "source": "site_id",
            "detail": "This field is required."
        },
        {
            "status": "400",
            "source": "name",
            "detail": "This field is required."
        },
        {
            "status": "400",
            "source": "slug",
            "detail": "This field is required."
        }
    ]
}

Dates

All dates are formatted according to ISO 8601

Publication status

Some resources have a status field that denotes their state in the publication workflow:

Id Status
1 Draft
2 Scheduled
3 Published
4 Deleted

The available statuses can be retrieved from the Statuses endpoint

Rights

Some resources have a rights JSON attribute which indicates which sites those resources can be used on. This can be as simple as

{ sites: [<UUID>] }

for a resource that is allowed only on one site, or can easily include many sites by listing their parent brands or units, or pools that they are in, by combining any of these properties:

{
    sites: [<UUID>, <UUID>, <UUID>],
    brands: [<UUID>, <UUID>, <UUID>],
    business_units: [<UUID>, <UUID>, <UUID>],
    pools: [<UUID>, <UUID>, <UUID>]
}

If the rights attribute is NULL or {} then the resource can be used on any site.

Source type

Source resources can have the following types:

Id Type
1 Generic
2 Image
3 Editorial
4 Site

Pagination

Rover uses page based pagination. It supports the following parameters:

Parameter Description Default
page result page to return 1 (implicit)
page_size results per page 100 (max: 500)

Example

GET https://{domain}/v2/content?page=3&page_size=10

By usings the prev and next objects in the links section of the response the client can traverse between pages in a simple way.

Result counts

By default, in addition to the result_count property that gives the number of resources in that page of the response, the meta section of the response contains count and (for legacy reasons) total_count properties which both give the total number of requested resources that could be paged through. This can be slow to calculate, and can be disabled per-request by passing a count=no querystring parameter.

You should definitely include that parameter if you don't need the total result count. If you are paging through results and need it to know how many pages there will be, at least disable it on requests for pages 2 and later.

Note that when you pass in count=no, the response's links section will always include a next URL, even if there are no more results; if you are paging through results and didn't get the count with page 1 then you'll have to be prepared to stop when you get a 404.

And in requests where you do need the total result count, please include a count=yes querystring parameter even though that's the default, so that we can someday switch the default to off.

Media Roles

Media related to Content, Tags, Collections, and Sections can also be assigned to roles (i.e the image for the content body)

Id Role
1 Slide
2 Social
3 Lead
4 Body
5 Marquee
6 Sponsored Marquee
7 Video Default Preview Image
8 Video Associated Image
9 Video Associated Video
10 Video Custom Preview Image

All media roles will automatically default to 'slide'

Video Types

Id Type
1 Asset
2 Live Stream
3 360 VR

Video type will automatically default to 'Asset'

Sorting

Resource collection results can be sorted via a sort paramater. Sorting is ascending by default. To sort descendingly, prefix the field with a - (hyphen).

Parameter Description
sort field(s) to sort by

Examples

Sort by id, ascending

GET https://{domain}/v2/content?sort=id

Sort by id, descending

GET https://{domain}/v2/content?sort=-id

Sort by id, ascending and title, descending

GET https://{domain}/v2/content?sort=id,-title

Filtering

Resource collections can be filtered with a number of different filters.

Note: Attempting to filter on a non-existent field will return a 400.

Filter Description Example
= Exact match between param and value param=value
:not Param does not match value param:not=value
:like Partial match between param and value param:like=value
:not-like Param does not partially match value param:not-like=value
:in Param matches any of the supplied values param:in=value1,value2,value3
:not-in Param does not match any of the supplied values param:not-in=value1,value2,value3
:null Param is or is not null. Only accepts true or false. Also works when checking if a record has a many-to-many association (e.g. does content have categories?) param:null=true or param:null=false
:gt Param is greater than value param:gt=value
:gte Param is greater than or equal to value param:gt=value
:lt Param is less than value param:lt=value
:lte Param is less than or equal to value param:lte=value
:between Param is between the two supplied values param:between=value1,value2

Example

GET https://{domain}/v2/content?title:like=beach&publish_from:gt=2015-01-15

Metadata filtering

The following filters are permissible when filtering on metadata or metadata_schema

Filter Description Example
= Exact match between param and value param=value
:not Param does not match value param:not=value
:contains Exact key membership match metadata:contains=key1,key2,...,keyN
:not-contains Key membership mismatch metadata:not-contains=key1,key2,...,keyN
:contains-any Key membership intersection metadata:contains-any=key1,key2,...,keyN
:not-contains-any Key membership disjoint metadata:not-contains-any=key1,key2,...,keyN

NOTES:

  • :contains and :not-contains and their -any variants only support top level key membership. They do NOT support nested keys. Filtering for a key within a hash, will not work.

  • :contains and :not-contains filters test for multiple-key membership, so you can supply more than one key and the filter will return all objects that have ALL the comma-separated specified keys in their metadata. E.g: metadata:contains=key1,key2,...,keyN will return all objects whose metadata contains key1 AND key2 AND ... keyN

  • :contains-any and :not-contains-any test for multiple-key intersection. What this means is that you can supply more than one key and the filter will return all objects that have ANY of the comma-separated specified keys in their metadata. E.g: metadata:contains-any=key1,key2,...,keyN will return all objects whose metadata contains key1 OR key2 OR ... keyN, and metadata:not-contains-any=key1,key2,...,keyN will return all objects whose metadata doesn't contain ANY of those keys.

  • metadata and metadata_schema are traversed using dot notation only for = and :not operators. E.g: ?metadata.foo.bar.baz=quux

Rights filtering

Two special filters select resources that can be shown on a particular site. Pass the rights filter parameter a comma-separated list of UUIDs of sites, brands, business units, and site pools to see only resources that can be shown on those sites or sites in those groups. Or as a shortcut, pass the site_has_rights filter just the UUID of the site you're editing, and it will look up that site's brand, unit, and pools for you. (This actually runs faster, since we then know in which rights index to look for each UUID.)

Response shaping

Rover provides a DSL for shaping the content of the response for list and detail views.

Note: Only the data object is affected.

  • Order sensitive
  • Embeddable via square brackets
  • Can be lists of selector strings
  • Are passed in using the fields parameter
Selector Description
+ Denotes inclusion, it is implied if missing
Denotes exclusion
* Wildcard - will match everything
[ ] Allow grouping of selectors
. A separator to denote a level change
, Separates a list of values
.. Denotes a range (ie [0..5])

###Examples

Return items with the id property only in a list view

fields=*.id

Return items with the id property only in a detail view (notice the omission of *.)

fields=id

Return all items with all properties except the body property

fields=*.-body

Return all items with all properties, but within the site property object exclude the metadata property

fields=*.*,*.site.-metadata

Return only the body of the second item (0 based index)

fields=1.body

Return all properties, but only the first 5 items

fields=[0..4]   or   items.[0,1,2,3,4]

Return only the body and tags from all items (the *), but only slug property of the first, second, and third tag (0 based index)

fields=*.body,tags.[0,1,2].[slug]
⚠️ **GitHub.com Fallback** ⚠️