Skip to content

Instantly share code, notes, and snippets.

@homam
Last active August 29, 2015 14:22
Show Gist options
  • Select an option

  • Save homam/dd13abb5e98fca991761 to your computer and use it in GitHub Desktop.

Select an option

Save homam/dd13abb5e98fca991761 to your computer and use it in GitHub Desktop.
Mobile Academy Content API

Content API Information

User Authentication

You should pass a special header containing the user ID in every API request: -H "x-userid:3"

We get the userid from Authentication API that is described in another document.

Please use x-userid:3 for testing purposes.

Response Headers

Response headers follow Web browser conventions:

Content-Type: application/json
Content-Length: 165476
Expires: Tue, 09 Jun 2015 09:41:49 GMT
x-content-type: courses
ETag: ec1ca1fae226cdd7a9dfcfd4a0c712d6

The app must cache the content up until te Expires time.

If the app needs to access the cached resource after the expiration time, it should make a cache-check request to the server by passing If-None-Match header, like:

curl ... -H "If-None-Match: ec1ca1fae226cdd7a9dfcfd4a0c712d6"

The server returns with 304 status and a new expiration time if the cached ETag is still valid:

HTTP/1.1 304 Not Modified
Expires: Tue, 09 Jun 2015 09:45:39 GMT

Otherwise the server returns with 200 status with new ETag and Expires and the full content of the requested resource in the response body.

List of all the Files

This API returns the list of all the files that should be downloaded in order. The app should download and cache these files in order whenever it can.

The app must always prioritize downloading resources that are needed or are related to the current actions by the user. (For example downloading the content or images for the current course that the user is viewing has higher priority than this queue).

curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/queue

Returns:

[
"http://pretty.mobileacademy.com/course/LosingMyVirginityRichardBranson",
"http://assets-preview.mobileacademy.com/LosingMyVirginityRichardBranson/images/artwork/poster.jpg", 
...
]

Static Text

Localized texts used in the app

curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/resource/website

Returns:

{
    "PrivacyPolicy": "Privacy Policy",
    "Tip_Default_Title": "Tip",
    "DidYouKnow_Default_Title": "Did you know?",
    "Tool_Default_Title": "",
    "QuestionInText_Default_Title": "Question",
    ...
}

List of Courses

curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/courses

Returns:

[
    {
        "id": "101",
        "availability": "Production",
        "icon": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/icon.png",
        "iconWide": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/icon-wide.png",
        "key": "HTWFIP2BookSummary",
        "keywords": [
            "negotiation",
            "influence",
            "friends",
            "popular",
            "impress",
            "leadership",
            "relationships"
        ],
        "path": "HTWFIP2BookSummary/text/HTWFIP2BookSummary-{lang}.json",
        "poster": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/poster.jpg",
        "title": {
            "af": "Hoe om Mense te Beïnvloed",
            "ar": "如何影响他人",
            "de": "Wie man Menschen beeinflusst",
            "en": "How To Influence People"
        },
        "type": "BookSummary"
    },
    ...
]
  • id :: Int : Course Id
  • key :: CourseKey :: String : Course Key
  • type :: Either BookSummary | BabelbayQA (there are two types of courses: standard courses: BookSummary and languages courses: BabelbayQA)
  • availability :: Either Development | Preview | Production
  • icon :: Image URL : 160x160 pixels
  • iconWide :: Image URL : 240x160 pixels
  • poster :: Image URL : 640x650 pixels
  • keywords :: [String] : To be used in Search feature in a later version
  • title :: [{lang : String}] : A dictionary of title of this course in every language in which it is available. Here lang is two letter ISO code for the language.
  • path :: String : Template URL for retrieving the content of the course in different locales, replace {lang} with the current users' language. Prepend http://assets-preview.mobileacademy.com/ to path to convert it to a URL template.

We need to be able to configure a build to filter the list of courses by their availability:

  • availability == 'Production'
  • availability in ['Production', 'Preview' , 'Development']
  • ...

The build should just ignore the courses that fail this filter.

Main View Layout

The layout of the main view. This layout is dynamic depending on user's ID and other factors.

Please check the iOS app to better understand the response form this API.

curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/layout

Response:

{
  "slides": [
    "MobilePhotography_QA",
    "SelfMakeover",
    "WhyWeGetFatBookSummary",
    ...
  ],
  "lists": [
    {
      "type": "small",
      "title": "Famous Books",
      "ltitle": "Famous_Books"
      "courses": [
        "LosingMyVirginityRichardBranson",
        "ThinkLikeARockStar",
        "BusinessExposed",
        ...
      ]
    },
    {
      "type": "large",
      "courses": [
        "EasyWaysToStopSmoking",
        "The7HabitsOfHighlyEffectivePeople",
        "WhyMenLoveBitches",
        ...
     }
     ...
  ]
}
  • slides :: [CourseKey] : Courses at the top of the main view.
  • lists :: [Row]

Course Content

curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1"  -H "x-userid:3" http://pretty.mobileacademy.com/course/HowChildrenSucceed

Response:

{
    "courseId": "118",
    "courseKey": "HowChildrenSucceed",
    "courseTitle": "How Children Succeed",
    "courseType": "BookSummary",
    "chapters": [
        {
            "title": "Introduction",
            "cards": [
                {
                    "question": "What is this course about?",
                    "answer": {
                        "shortAnswer": "What makes children become successful adults",
                        "longAnswer": [
                            {
                                "type": "text",
                                "text": "This course is based on the book, 'How Children Succeed: Grit, Curiosity and the Hidden Power of Character'. ... .\nPublished: 2012"
                            }
                        ]
                    },
                    "incorrectAnswers": []
                },
                ...
            ]
        },
        ...
   ]
}
type Course = BookSummaryCourse | BabelbayQACourse

data BookSummaryCourse = BookSummaryCourse {
    courseId :: String, 
    courseKey :: String, 
    courseTitle :: String, 
    courseType :: "BookSummary"
    chapters :: [Chapter]
}

data Chapter = Chapter {
    title :: String,
    cards :: [Card]
}

data Card = Card {
    question :: String,
    answer :: {shortAnswer :: String, longAnswer :: [Control], bonus :: Bonus},
    incorrectAnswers :: [String]
    image :: Image
}

type Control = Text | List | Links

data Text = Text {
    type :: "text"
    text :: String
}

data Bonus = Bonus {
    type :: (didYouKnow | definition | funFact | tip | caseStudy | example | quote)
    title :: String,
    controls :: [Control]
}

data List = List {
    type :: (simpleList | simpleOList)
    items :: [String]
}

data Links = Links {
    type :: "links"
    links :: [{host :: String, link :: String}]
}

data Image = Image {
   source :: URL
   position :: (shortAnswer | longAnswer | bonus)
   size :: {width, height, bytes}
}
## Content API Information
### User Authentication
You should pass a special header containing the user ID in every API request: `-H "x-userid:3"`
We get the `userid` from _Authentication API_ that is described in another document.
Please use `x-userid:3` for testing purposes.
### Response Headers
Response headers follow Web browser conventions:
```
Content-Type: application/json
Content-Length: 165476
Expires: Tue, 09 Jun 2015 09:41:49 GMT
x-content-type: courses
ETag: ec1ca1fae226cdd7a9dfcfd4a0c712d6
```
The app must cache the content up until te `Expires` time.
If the app needs to access the cached resource after the expiration time, it should make a cache-check request to the server by passing `If-None-Match` header, like:
```
curl ... -H "If-None-Match: ec1ca1fae226cdd7a9dfcfd4a0c712d6"
```
The server returns with `304` status and a new expiration time if the cached `ETag` is still valid:
```
HTTP/1.1 304 Not Modified
Expires: Tue, 09 Jun 2015 09:45:39 GMT
```
Otherwise the server returns with `200` status with new `ETag` and `Expires` and the full content of the requested resource in the response body.
### List of all the Files
This API returns the list of all the files that should be downloaded in order. The app should download and cache these files in order whenever it can.
The app must always prioritize downloading resources that are needed or are related to the current actions by the user. (For example downloading the content or images for the current course that the user is viewing has higher priority than this queue).
```
curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/queue
```
Returns:
```
[
"http://pretty.mobileacademy.com/course/LosingMyVirginityRichardBranson",
"http://assets-preview.mobileacademy.com/LosingMyVirginityRichardBranson/images/artwork/poster.jpg",
...
]
```
### Static Text
Localized texts used in the app
```
curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/resource/website
```
Returns:
```
{
"PrivacyPolicy": "Privacy Policy",
"Tip_Default_Title": "Tip",
"DidYouKnow_Default_Title": "Did you know?",
"Tool_Default_Title": "",
"QuestionInText_Default_Title": "Question",
...
}
```
### List of Courses
```
curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/courses
```
Returns:
```
[
{
"id": "101",
"availability": "Production",
"icon": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/icon.png",
"iconWide": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/icon-wide.png",
"key": "HTWFIP2BookSummary",
"keywords": [
"negotiation",
"influence",
"friends",
"popular",
"impress",
"leadership",
"relationships"
],
"path": "HTWFIP2BookSummary/text/HTWFIP2BookSummary-{lang}.json",
"poster": "http://assets-preview.mobileacademy.com/HTWFIP2BookSummary/images/artwork/poster.jpg",
"title": {
"af": "Hoe om Mense te Beïnvloed",
"ar": "如何影响他人",
"de": "Wie man Menschen beeinflusst",
"en": "How To Influence People"
},
"type": "BookSummary"
},
...
]
```
* `id :: Int` : Course Id
* `key :: CourseKey :: String` : Course Key
* `type :: Either BookSummary | BabelbayQA` (there are two types of courses: standard courses: BookSummary and languages courses: BabelbayQA)
* `availability :: Either Development | Preview | Production`
* `icon :: Image URL` : 160x160 pixels
* `iconWide :: Image URL` : 240x160 pixels
* `poster :: Image URL` : 640x650 pixels
* `keywords :: [String]` : To be used in _Search_ feature in a later version
* `title :: [{lang : String}]` : A dictionary of title of this course in every language in which it is available. Here `lang` is two letter ISO code for the language.
* `path :: String` : Template URL for retrieving the content of the course in different locales, replace `{lang}` with the current users' language. Prepend `http://assets-preview.mobileacademy.com/` to `path` to convert it to a URL template.
We need to be able to configure a _build_ to filter the list of courses by their availability:
* `availability == 'Production'`
* `availability in ['Production', 'Preview' , 'Development']`
* ...
The build should just ignore the courses that fail this filter.
### Main View Layout
The layout of the main view. This layout is dynamic depending on user's ID and other factors.
Please check the iOS app to better understand the response form this API.
```
curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/layout
```
Response:
```
{
"slides": [
"MobilePhotography_QA",
"SelfMakeover",
"WhyWeGetFatBookSummary",
...
],
"lists": [
{
"type": "small",
"title": "Famous Books",
"ltitle": "Famous_Books"
"courses": [
"LosingMyVirginityRichardBranson",
"ThinkLikeARockStar",
"BusinessExposed",
...
]
},
{
"type": "large",
"courses": [
"EasyWaysToStopSmoking",
"The7HabitsOfHighlyEffectivePeople",
"WhyMenLoveBitches",
...
}
...
]
}
```
* `slides :: [CourseKey]` : Courses at the top of the main view.
* `lists :: [Row]`
* `Row :: type, ltitle, courses`
* `type :: Either small | big`
* `ltitle :: String` in Static Text, http://pretty.mobileacademy.com/resource/website resource
* `courses :: [CourseKey]`
### Course Content
```
curl -H "x-version-courses:1" -H "x-version-course:1" -H "x-version-layout:1" -H "x-version-faq:1" -H "x-lang:en" -H "x-version-website:1" -H "x-env:release" -H "x-version-privacy:1" -H "x-version-subscription:1" -H "x-userid:3" http://pretty.mobileacademy.com/course/HowChildrenSucceed
```
Response:
```
{
"courseId": "118",
"courseKey": "HowChildrenSucceed",
"courseTitle": "How Children Succeed",
"courseType": "BookSummary",
"chapters": [
{
"title": "Introduction",
"cards": [
{
"question": "What is this course about?",
"answer": {
"shortAnswer": "What makes children become successful adults",
"longAnswer": [
{
"type": "text",
"text": "This course is based on the book, 'How Children Succeed: Grit, Curiosity and the Hidden Power of Character'. ... .\nPublished: 2012"
}
]
},
"incorrectAnswers": []
},
...
]
},
...
]
}
```
```Haskell
type Course = BookSummaryCourse | BabelbayQACourse
data BookSummaryCourse = BookSummaryCourse {
courseId :: String,
courseKey :: String,
courseTitle :: String,
courseType :: "BookSummary"
chapters :: [Chapter]
}
data Chapter = Chapter {
title :: String,
cards :: [Card]
}
data Card = Card {
question :: String,
answer :: {shortAnswer :: String, longAnswer :: [Control], bonus :: Bonus},
incorrectAnswers :: [String]
image :: Image
}
type Control = Text | List | Links
data Text = Text {
type :: "text"
text :: String
}
data Bonus = Bonus {
type :: (didYouKnow | definition | funFact | tip | caseStudy | example | quote)
title :: String,
controls :: [Control]
}
data List = List {
type :: (simpleList | simpleOList)
items :: [String]
}
data Links = Links {
type :: "links"
links :: [{host :: String, link :: String}]
}
data Image = Image {
source :: URL
position :: (shortAnswer | longAnswer | bonus)
size :: {width, height, bytes}
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment