{"action":"created","comment":{"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/24182369","id":24182369,"diff_hunk":"@@ -0,0 +1,119 @@\n+---\n+title: Utilising API Blueprint in API Clients\n+excerpt: Imagine an API client when you specify which resource and action you want to perform from an API Blueprint.\n+layout: post\n+date: 2015-02-06 18:00:00 +0000\n+author: kyle\n+published: true\n+comments: true\n+---\n+\n+I’m excited to release a new way to interface to API Blueprints. A client-side framework in Swift that allows you to introspect and perform actions at run-time.\n+\n+Imagine an API client when you specify which resource and action you want to perform from an API Blueprint, it can use the already defined information from a blueprint to build the request without having to duplicate the information such as the HTTP method and URI from your blueprint. This allows you to start building smarter clients which can evolve at run-time based on the blueprint.\n+\n+The SDK is built on-top of a framework we’ve built called the [Representor](https://github.com/the-hypermedia-project/charter), which is designed to be a canonical representation of a hypermedia message in multiple languages. One of the key constraints to Representational State Transfer (REST) is Hypermedia as the Engine of State (HATEOS).  The message from the server itself should contain information about how to transition to other states along with links to other resources.\n+\n+The Representor is a structure providing this functionality along with the ability to deserialise Hypermedia formats such as [HAL](http://stateless.co/hal_specification.html) and [Siren](https://github.com/kevinswiber/siren). The Representer contains a couple of properties, one of them is it’s transitions to other states, along with how the current resource links to other resources.\n+\n+Since a blueprint is effectively a document which specifies all of the transitions (actions) in your API, we’ve built on-top of the Representor and added the ability to deserialise an API Blueprint into a collection of transitions.\n+\n+This allows us to decouple an API client from the server-side implementation, we no longer have to know about the URIs to each resource and the HTTP methods in our code. We can negotiate these at run-time, similar to how with HATEOS we follow links, we can follow links from an API Blueprint.\n+\n+## Example\n+\n+Let’s walk though how to load an API Blueprint and perform transitions in Swift. First of all, we’re going to load our blueprint file that’s embedded in our application. You’re not limited to embedding it in your application. You could even retrieve it dynamically at run-time.\n+\n+```swift\n+let blueprint = Blueprint(named: \"blueprint.json\", bundle: nil)\n+```\n+\n+Once you’ve loaded your blueprint, you can retrieve the different actions as [transitions](https://github.com/the-hypermedia-project/charter/blob/master/reference/hypermedia-elements.md#transitions) from your blueprint.\n+\n+This example is going to make use of one of our example blueprints, “Polls API”. I’ve pulled out an excerpt of the example blueprint and it looks something like the following. You can find the full version over in our [examples](https://github.com/apiaryio/api-blueprint/blob/kylef/polls-example/examples/Polls%20API.md).\n+\n+```markdown\n+# Polls\n+Polls is a simple web service that allows consumers to view polls and vote in them.\n+\n+## Group Question\n+Resource related to questions in the API.\n+\n+## Question [/questions/{question_id}]\n++ Parameters\n+    + question_id (number) ... ID of the Question in form of an integer\n+\n+### View a question detail [GET]\n+\n+## Choice [/questions/{question_id}/choices/{choice_id}]\n+\n++ Parameters\n+    + question_id (number) ... ID of the Question in form of an integer\n+    + choice_id (number) ... ID of the Choice in form of an integer\n+\n+### Vote [PUT]\n+\n+This action allows you to vote on a question's choice.\n+\n+## Questions collection [/questions{?page}]\n++ Parameters\n+    + page (optional, number) ... The page of questions to return\n+\n+### List all questions [GET]\n+### Create a new question [POST]\n+```\n+\n+We can pull out any of the actions from our blueprint by the resource and action name in Swift:\n+\n+```swift\n+if let transition = blueprint?.transition(\"Choice\", action: \"Vote\") {\n+}\n+```\n+\n+This transition allows us to introspect it’s values at run-time, allowing us to retrieve protocol information such as the HTTP method and URI along with all the URI parameters.\n+\n+```swift\n+println(transition.uri)\n+println(transition.method)\n+\n+for (name, parameter) in transition.parameters {\n+  println(name)\n+  println(\"\\(parameter.value) \\(parameter.defaultValue)\")\n+}\n+```\n+\n+We can use the elegant Swift HTTP networking library [Alamofire](https://github.com/Alamofire/Alamofire) along with some convenience methods we’ve built to perform HTTP requests from our transition directly.\n+\n+```swift\n+let baseURL = NSURL(string: \"http://polls.apiblueprint.org/\")","path":"_posts/2015-02-06-Utilising-API-Blueprint-in-API-Clients.md","position":88,"original_position":88,"commit_id":"c21bc53c439808ba80e7d3ea8b08142552c6dd18","original_commit_id":"c21bc53c439808ba80e7d3ea8b08142552c6dd18","user":{"login":"zdne","id":613617,"avatar_url":"https://avatars.githubusercontent.com/u/613617?v=3","gravatar_id":"","url":"https://api.github.com/users/zdne","html_url":"https://github.com/zdne","followers_url":"https://api.github.com/users/zdne/followers","following_url":"https://api.github.com/users/zdne/following{/other_user}","gists_url":"https://api.github.com/users/zdne/gists{/gist_id}","starred_url":"https://api.github.com/users/zdne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zdne/subscriptions","organizations_url":"https://api.github.com/users/zdne/orgs","repos_url":"https://api.github.com/users/zdne/repos","events_url":"https://api.github.com/users/zdne/events{/privacy}","received_events_url":"https://api.github.com/users/zdne/received_events","type":"User","site_admin":false},"body":"Out of curiosity – isn't that root URL hidden somewhere in the blueprint Adapter? ","created_at":"2015-02-05T17:47:45Z","updated_at":"2015-02-05T17:47:45Z","html_url":"https://github.com/apiaryio/apiaryio.github.com/pull/38#discussion_r24182369","pull_request_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38","_links":{"self":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/24182369"},"html":{"href":"https://github.com/apiaryio/apiaryio.github.com/pull/38#discussion_r24182369"},"pull_request":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38"}}},"pull_request":{"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38","id":28551718,"html_url":"https://github.com/apiaryio/apiaryio.github.com/pull/38","diff_url":"https://github.com/apiaryio/apiaryio.github.com/pull/38.diff","patch_url":"https://github.com/apiaryio/apiaryio.github.com/pull/38.patch","issue_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/38","number":38,"state":"open","locked":false,"title":"[Post] Utilising API Blueprint in API clients (Swift)","user":{"login":"kylef","id":44164,"avatar_url":"https://avatars.githubusercontent.com/u/44164?v=3","gravatar_id":"","url":"https://api.github.com/users/kylef","html_url":"https://github.com/kylef","followers_url":"https://api.github.com/users/kylef/followers","following_url":"https://api.github.com/users/kylef/following{/other_user}","gists_url":"https://api.github.com/users/kylef/gists{/gist_id}","starred_url":"https://api.github.com/users/kylef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kylef/subscriptions","organizations_url":"https://api.github.com/users/kylef/orgs","repos_url":"https://api.github.com/users/kylef/repos","events_url":"https://api.github.com/users/kylef/events{/privacy}","received_events_url":"https://api.github.com/users/kylef/received_events","type":"User","site_admin":false},"body":"#### :warning: work in progress :warning: \r\n\r\n- [ ] Review draft post @zdne \r\n- [x] Fix code-examples (they need to be highlighted correctly)\r\n- [x] Release representor 0.2.0\r\n- [ ] Update link to https://github.com/apiaryio/api-blueprint/pull/148 once merged\r\n- [ ] [Release code examples](https://github.com/apiaryio/apiary/pull/2107)\r\n- [x] Include image of code examples","created_at":"2015-02-03T13:26:30Z","updated_at":"2015-02-05T17:47:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8e8db8739f8a68701511584113c1cec7b9832ddd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38/commits","review_comments_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38/comments","review_comment_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/{number}","comments_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/38/comments","statuses_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/c21bc53c439808ba80e7d3ea8b08142552c6dd18","head":{"label":"apiaryio:kylef/representor-swift-blueprint","ref":"kylef/representor-swift-blueprint","sha":"c21bc53c439808ba80e7d3ea8b08142552c6dd18","user":{"login":"apiaryio","id":765943,"avatar_url":"https://avatars.githubusercontent.com/u/765943?v=3","gravatar_id":"","url":"https://api.github.com/users/apiaryio","html_url":"https://github.com/apiaryio","followers_url":"https://api.github.com/users/apiaryio/followers","following_url":"https://api.github.com/users/apiaryio/following{/other_user}","gists_url":"https://api.github.com/users/apiaryio/gists{/gist_id}","starred_url":"https://api.github.com/users/apiaryio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apiaryio/subscriptions","organizations_url":"https://api.github.com/users/apiaryio/orgs","repos_url":"https://api.github.com/users/apiaryio/repos","events_url":"https://api.github.com/users/apiaryio/events{/privacy}","received_events_url":"https://api.github.com/users/apiaryio/received_events","type":"Organization","site_admin":false},"repo":{"id":1696866,"name":"apiaryio.github.com","full_name":"apiaryio/apiaryio.github.com","owner":{"login":"apiaryio","id":765943,"avatar_url":"https://avatars.githubusercontent.com/u/765943?v=3","gravatar_id":"","url":"https://api.github.com/users/apiaryio","html_url":"https://github.com/apiaryio","followers_url":"https://api.github.com/users/apiaryio/followers","following_url":"https://api.github.com/users/apiaryio/following{/other_user}","gists_url":"https://api.github.com/users/apiaryio/gists{/gist_id}","starred_url":"https://api.github.com/users/apiaryio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apiaryio/subscriptions","organizations_url":"https://api.github.com/users/apiaryio/orgs","repos_url":"https://api.github.com/users/apiaryio/repos","events_url":"https://api.github.com/users/apiaryio/events{/privacy}","received_events_url":"https://api.github.com/users/apiaryio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apiaryio/apiaryio.github.com","description":"Apiary Blog","fork":false,"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com","forks_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/forks","keys_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/teams","hooks_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/hooks","issue_events_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/events{/number}","events_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/events","assignees_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/assignees{/user}","branches_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/branches{/branch}","tags_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/tags","blobs_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/refs{/sha}","trees_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/{sha}","languages_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/languages","stargazers_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/stargazers","contributors_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/contributors","subscribers_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/subscribers","subscription_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/subscription","commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/commits{/sha}","git_commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/commits{/sha}","comments_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/comments{/number}","issue_comment_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/comments/{number}","contents_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/contents/{+path}","compare_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/merges","archive_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/downloads","issues_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues{/number}","pulls_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls{/number}","milestones_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/milestones{/number}","notifications_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/labels{/name}","releases_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/releases{/id}","created_at":"2011-05-03T15:39:36Z","updated_at":"2015-01-16T12:34:56Z","pushed_at":"2015-02-05T17:11:55Z","git_url":"git://github.com/apiaryio/apiaryio.github.com.git","ssh_url":"git@github.com:apiaryio/apiaryio.github.com.git","clone_url":"https://github.com/apiaryio/apiaryio.github.com.git","svn_url":"https://github.com/apiaryio/apiaryio.github.com","homepage":"http://blog.apiary.io/","size":18846,"stargazers_count":6,"watchers_count":6,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3,"mirror_url":null,"open_issues_count":1,"forks":3,"open_issues":1,"watchers":6,"default_branch":"master"}},"base":{"label":"apiaryio:master","ref":"master","sha":"adf7d6554f385789c8edd483dfb04a7ebb792666","user":{"login":"apiaryio","id":765943,"avatar_url":"https://avatars.githubusercontent.com/u/765943?v=3","gravatar_id":"","url":"https://api.github.com/users/apiaryio","html_url":"https://github.com/apiaryio","followers_url":"https://api.github.com/users/apiaryio/followers","following_url":"https://api.github.com/users/apiaryio/following{/other_user}","gists_url":"https://api.github.com/users/apiaryio/gists{/gist_id}","starred_url":"https://api.github.com/users/apiaryio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apiaryio/subscriptions","organizations_url":"https://api.github.com/users/apiaryio/orgs","repos_url":"https://api.github.com/users/apiaryio/repos","events_url":"https://api.github.com/users/apiaryio/events{/privacy}","received_events_url":"https://api.github.com/users/apiaryio/received_events","type":"Organization","site_admin":false},"repo":{"id":1696866,"name":"apiaryio.github.com","full_name":"apiaryio/apiaryio.github.com","owner":{"login":"apiaryio","id":765943,"avatar_url":"https://avatars.githubusercontent.com/u/765943?v=3","gravatar_id":"","url":"https://api.github.com/users/apiaryio","html_url":"https://github.com/apiaryio","followers_url":"https://api.github.com/users/apiaryio/followers","following_url":"https://api.github.com/users/apiaryio/following{/other_user}","gists_url":"https://api.github.com/users/apiaryio/gists{/gist_id}","starred_url":"https://api.github.com/users/apiaryio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apiaryio/subscriptions","organizations_url":"https://api.github.com/users/apiaryio/orgs","repos_url":"https://api.github.com/users/apiaryio/repos","events_url":"https://api.github.com/users/apiaryio/events{/privacy}","received_events_url":"https://api.github.com/users/apiaryio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apiaryio/apiaryio.github.com","description":"Apiary Blog","fork":false,"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com","forks_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/forks","keys_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/teams","hooks_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/hooks","issue_events_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/events{/number}","events_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/events","assignees_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/assignees{/user}","branches_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/branches{/branch}","tags_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/tags","blobs_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/refs{/sha}","trees_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/{sha}","languages_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/languages","stargazers_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/stargazers","contributors_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/contributors","subscribers_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/subscribers","subscription_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/subscription","commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/commits{/sha}","git_commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/git/commits{/sha}","comments_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/comments{/number}","issue_comment_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/comments/{number}","contents_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/contents/{+path}","compare_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/merges","archive_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/downloads","issues_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues{/number}","pulls_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls{/number}","milestones_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/milestones{/number}","notifications_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/labels{/name}","releases_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/releases{/id}","created_at":"2011-05-03T15:39:36Z","updated_at":"2015-01-16T12:34:56Z","pushed_at":"2015-02-05T17:11:55Z","git_url":"git://github.com/apiaryio/apiaryio.github.com.git","ssh_url":"git@github.com:apiaryio/apiaryio.github.com.git","clone_url":"https://github.com/apiaryio/apiaryio.github.com.git","svn_url":"https://github.com/apiaryio/apiaryio.github.com","homepage":"http://blog.apiary.io/","size":18846,"stargazers_count":6,"watchers_count":6,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3,"mirror_url":null,"open_issues_count":1,"forks":3,"open_issues":1,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38"},"html":{"href":"https://github.com/apiaryio/apiaryio.github.com/pull/38"},"issue":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/38"},"comments":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/38/comments"},"review_comments":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38/comments"},"review_comment":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/38/commits"},"statuses":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/c21bc53c439808ba80e7d3ea8b08142552c6dd18"}}}}