{"action":"created","comment":{"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/45763303","id":45763303,"diff_hunk":"@@ -0,0 +1,27 @@\n+---\n+title: Client first\n+excerpt: Think about your clients -- both humans and machines -- before starting to design your constraints\n+layout: post\n+date: 2015-12-01 08:00:00 -0700\n+author: almad\n+published: true\n+comments: true\n+---\n+\n+If there is a key in your payload but no client to use it, does it really exist?\n+\n+Every architecture starts with constraints, and every constraint is introduced to achieve desirable results. In order to get your API goals right, you inevitably need to think about how your API is going to be consumed.\n+\n+Writing things down into an API Description is a great start, but it's only the beginning. Without actually talking and prototyping with the other side, chances are that you are going to put emphasis on the needs of the server and ignore the needs of the client.\n+\n+One of the big dangers involved is imagining API usage _for_ the clients. If you don't have actual constraints in API that force them to behave that way, your design will most probably stay in form of proposal.\n+\n+Want client developers to handle failures gracefully? Return failure responses more often. Want them to treat your API as state machine and navigate through links? Obfuscate URLs and change them often. Confident in our API change coping strategy? Do (breaking) changes daily.\n+\n+Engineering is a hard game of trade-offs; intents above may not be for you. But unless you actually fullfil your intents (maybe to their extreme), you can't rely on them.\n+\n+All new approaches in APIs are chicken-and-egg problem where agreement must be reached, and I argue that clients are the more powerful force here.\n+\n+Without clients sending `ETag` back, you don't have caching, you have larger headers. Without API clients actually following HAL links, you don't have hypermedia API, you have inflated payloads. Without terrific and safe execution environment, you don't have Code On Demand, you have injected garbage.","path":"_posts/2015-12-01-Client-First.md","position":25,"original_position":25,"commit_id":"44490fdb9d257d688bf546cd91d3bac4b429cfb1","original_commit_id":"44490fdb9d257d688bf546cd91d3bac4b429cfb1","user":{"login":"smizell","id":130959,"avatar_url":"https://avatars.githubusercontent.com/u/130959?v=3","gravatar_id":"","url":"https://api.github.com/users/smizell","html_url":"https://github.com/smizell","followers_url":"https://api.github.com/users/smizell/followers","following_url":"https://api.github.com/users/smizell/following{/other_user}","gists_url":"https://api.github.com/users/smizell/gists{/gist_id}","starred_url":"https://api.github.com/users/smizell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smizell/subscriptions","organizations_url":"https://api.github.com/users/smizell/orgs","repos_url":"https://api.github.com/users/smizell/repos","events_url":"https://api.github.com/users/smizell/events{/privacy}","received_events_url":"https://api.github.com/users/smizell/received_events","type":"User","site_admin":false},"body":"\"...you don't have a hypermedia API...\"\r\n\r\n\"With a terrific and safe...\"","created_at":"2015-11-24T17:00:46Z","updated_at":"2015-11-24T17:00:46Z","html_url":"https://github.com/apiaryio/apiaryio.github.com/pull/74#discussion_r45763303","pull_request_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74","_links":{"self":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/comments/45763303"},"html":{"href":"https://github.com/apiaryio/apiaryio.github.com/pull/74#discussion_r45763303"},"pull_request":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74"}}},"pull_request":{"url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74","id":51442999,"html_url":"https://github.com/apiaryio/apiaryio.github.com/pull/74","diff_url":"https://github.com/apiaryio/apiaryio.github.com/pull/74.diff","patch_url":"https://github.com/apiaryio/apiaryio.github.com/pull/74.patch","issue_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/74","number":74,"state":"open","locked":false,"title":"Clients first","user":{"login":"Almad","id":44565,"avatar_url":"https://avatars.githubusercontent.com/u/44565?v=3","gravatar_id":"","url":"https://api.github.com/users/Almad","html_url":"https://github.com/Almad","followers_url":"https://api.github.com/users/Almad/followers","following_url":"https://api.github.com/users/Almad/following{/other_user}","gists_url":"https://api.github.com/users/Almad/gists{/gist_id}","starred_url":"https://api.github.com/users/Almad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Almad/subscriptions","organizations_url":"https://api.github.com/users/Almad/orgs","repos_url":"https://api.github.com/users/Almad/repos","events_url":"https://api.github.com/users/Almad/events{/privacy}","received_events_url":"https://api.github.com/users/Almad/received_events","type":"User","site_admin":false},"body":"Up for discussion.\r\n\r\n@smizell I actually thought about this one as we had a chat about Plutonium. Would welcome feedback, and whether this actually makes sense ;) ","created_at":"2015-11-21T15:10:49Z","updated_at":"2015-11-24T17:00:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e32ba0ea79db180eb5e2328fd62d0fe86301d6aa","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74/commits","review_comments_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74/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/74/comments","statuses_url":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/44490fdb9d257d688bf546cd91d3bac4b429cfb1","head":{"label":"apiaryio:almad/client-first","ref":"almad/client-first","sha":"44490fdb9d257d688bf546cd91d3bac4b429cfb1","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-05-14T10:14:51Z","pushed_at":"2015-11-21T15:10:50Z","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":"https://blog.apiary.io/","size":22810,"stargazers_count":7,"watchers_count":7,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3,"mirror_url":null,"open_issues_count":3,"forks":3,"open_issues":3,"watchers":7,"default_branch":"master"}},"base":{"label":"apiaryio:master","ref":"master","sha":"b8e7987a5d1e0e369f946712ffc74766aa834cc8","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-05-14T10:14:51Z","pushed_at":"2015-11-21T15:10:50Z","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":"https://blog.apiary.io/","size":22810,"stargazers_count":7,"watchers_count":7,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3,"mirror_url":null,"open_issues_count":3,"forks":3,"open_issues":3,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74"},"html":{"href":"https://github.com/apiaryio/apiaryio.github.com/pull/74"},"issue":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/74"},"comments":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/issues/74/comments"},"review_comments":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/pulls/74/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/74/commits"},"statuses":{"href":"https://api.github.com/repos/apiaryio/apiaryio.github.com/statuses/44490fdb9d257d688bf546cd91d3bac4b429cfb1"}}}}