Skip to content

Instantly share code, notes, and snippets.

@archie
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save archie/9918869 to your computer and use it in GitHub Desktop.
Save archie/9918869 to your computer and use it in GitHub Desktop.

Demokratiappen API

Draft 1

Inspiration gathered from Foursquare and Bit.ly APIs.

Guidelines

Request/Response formats

All requests are made against https://demokratiappen.se/api/v1 and all request bodies are expected to be json formatted. This applies even if the Content-Type: application/json is not set.

Responses are wrapped in a json envelope:

{
  "status_code": int, 
  "status_text": string, 
  "response": json
}

status_code is the same HTTP status code that is returned in the header and the status_text is a human readable description of the error. Where possible the error is more specific than what the HTTP code represents.

Rate limiting

TODO

Authentication

OAuth2 ?

TBD

OAuth2 using username and password

Demokratiappen supports a subset of the OAuth2 specification for authentication using username and password.

A POST request is sent to /oauth/access_token as follows:

POST /oauth/access_token HTTP/1.1
Host: https://demokratiappen.se/api/v1
Authorization: Basic czZCaGRSa3F0MzpnWDF
Content-Type: application/json

{
  "grant_type": "password",
  "username": string,
  "password": string
}

Where Authorization is mandatory and contains the value "Basic " + base64encode(client_id + ":" + client_secret). Client ID and client secret can be obtained here: .

The response, if authorization is successful, includes an access token.

{
  "access_token": "e663e30818201d28dd07803e57333bed4f15803a"
}

Alternatively, a curl request may be executed as this:

curl -u "CLIENT_ID:CLIENT_SECRET" -H "Content-Type: application/json" -d '{"grant_type=password", "username=USERNAME", "password=PASSWORD" }' https://demokratiappen.se/api/v1/oauth/access_token

Users

Requires user authentication.

GET /users/me returns 200 OK and a user object.

{
  "userid": string,
  "username": string,
  "email": string,
  "created": datetime,
  "updated": datetime,
  "summary": {
    "tags": int,
    "articles": int
  },
  "tags": "https://demokratiappen.se/api/v1/users/me/tags",
  "articles": "https://demokratiappen.se/api/v1/users/me/articles",
}

If not authenticated, return 401 Unauthorized.

Update user information

POST /users/me where body includes a JSON object that specifies which fields to update.

{
  "email": "new email"
}

Return 405 Method Not Allowed if trying to modify a field which is not modifieable.

Retrieve tags by user

GET /users/me/tags returns 200 OK and a list of all tags made by user.

{
  "userid": string,
  "tags": [
    {
      "tagid": string,
      "name": string,
      "type": string, 
      "counts": {
        "negative": int,
        "positive": int
      },
      "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
    }
  ]
}

Possible optional parameters to request:

  • limit=int
  • offset=int

GET /users/me/tags/:tagid to get a specific tag.

{
  "userid": string,
  "tag": {
    "tagid": string,
    "name": string,
    "type": string, 
    "counts": {
      "negative": int,
      "positive": int
    },
    "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
  }
}

Returns 404 Not Found if user hasn't tagged that particular tag.

Retrieve articles by user

GET /users/me/articles returns 200 OK and a list of articles by user.

{
  "userid": string,
  "articles": [
    {
      "articleid": string, 
      "title": string,
      "url": string,
      "ref": "https://demokratiappen.se/api/v1/articles/:articleid"
      "tagsInArticle": [
        {
          "tagid": string,
          "name": string,
          "type": string,
          "counts": {
            "negative": int,
            "positive": int
          },
          "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
        }
      ]
    }
  ]
}

Possible optional parameters to request:

  • limit=int
  • offset=int

GET /users/me/articles/:articleid to get a specific article, returns 200 OK and

{
  "userid": string,
  "article": {
    "articleid": string, 
    "title": string,
    "url": string,
    "ref": "https://demokratiappen.se/api/v1/articles/:articleid"
    "tagsInArticle": [
      {
        "tagid": string,
        "name": string,
        "type": string,
        "counts": {
          "negative": int,
          "positive": int
        },
        "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
      }
    ]
  }
}

Returns 404 Not Found if user hasn't saved that particular article.

Tags

Retrieve all tags

Make a GET /tags with the possible optional parameters

  • limit=int
  • offset=int

Returns 200 OK and

{
  "tags": [
    {
      "tagid": string,
      "name": string,
      "type": string, 
      "totalCounts": {
        "negative": int,
        "positive": int,
        "seen": int
      },
      "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
    }
  ],
  // if limit is used
  "limit": int,
  "offset": int,
  "next": "https://demokratiappen.se/api/v1/tags?offset=(offset+limit)&limit=limit"
}

Retrieve a specific tag

Make a GET /tags/:tagid, returns 200 OK and

{
  "tagid": string,
  "name": string,
  "type": string, 
  "totalCounts": {
    "negative": int,
    "positive": int,
    "seen": int
  },
  "ref": "https://demokratiappen.se/api/v1/tags/:tagid",
  "inArticles": [
    {
      "articleid": string,
      "ref": "https://demokratiappen.se/api/v1/articles/:articleid"
    }
  ]
}

Articles

Retrieve all articles

Make a GET /articles/ with possible optional parameters

  • limit=int
  • offset=int
  • query=tag1,tag2,tag2 - could possible be made more specific, e.g., contains

and returns 200 OK and the following body

{
  "articles": [
    {
      "articleid": string, 
      "title": string,
      "url": string, 
      "ref": "https://demokratiappen.se/api/v1/articles/:articleid",
      "tagsInArticle": [
        {
          "tagid": string, 
          "name": string, 
          "type": string, 
          "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
        }
      ],
      "extract": string, // ingress or similar from article
      "matches": [
        { 
          "tagid": string,
          "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
        }
      ] // only if query param is provided
    }
  ],
  // only if limit is provided
  "offset": int,
  "limit": int,
  "next": "https://demokratiappen.se/api/v1/articles?offset=(offset+limit)&limit=limit"
}

Retrieve a specific article

Make a GET /articles/:articleid. There are no optional parameters.

{
  "articleid": string, 
  "title": string,
  "url": string, 
  "ref": "https://demokratiappen.se/api/v1/articles/:articleid",
  "tagsInArticle": [
    {
      "tagid": string, 
      "name": string, 
      "type": string, 
      "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
    }
  ],
  "fulltext": string
}

Save an article

Requires user authentication.

POST /articles/add returns 201 Created and the new article object. (TBD: consider POST /users/me/articles)

Request (all fields are optional unless otherwise stated)

{
  "url": string, // required
  "title": string, 
  "theme": string
}

Response

{
  "article": {
    "articleid": string, 
    "title": string,
    "url": string,
    "ref": "https://demokratiappen.se/api/v1/articles/:articleid"
    "tagsInArticle": [
      {
        "tagid": string,
        "name": string,
        "type": string,
        "ref": "https://demokratiappen.se/api/v1/tags/:tagid"
      }
    ]
  }
}

Once an article is created, a second request can be sent to rate the article. Only one rate request is allowed. All subsequent rate requests return 403 Forbidden.

To rate an article, send a POST /articles/:articleid/rate with the body:

{
  "ratings": [
    {
      "tagid": string,
      "rating": string // negative || positive
    }
  ]
}

Correct requests return 200 OK with an empty body.

If a tagid is not included the tag is left unrated. If at least one tagid is not correct or does not apply for the articleid an error response 400 Bad Request is returned. The body details which tagid is failing. Either all is applied or an error is generated and rating can be redone.

{
  "status_code": int,
  "status_text": string, // message to user describing the error
  "response": {
    "failedTagids": [:tagid]
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment