{"action":"created","comment":{"url":"https://api.github.com/repos/ipfs/specs/pulls/comments/45575190","id":45575190,"diff_hunk":"@@ -0,0 +1,175 @@\n+# IPFS API Implementation Doc\n+\n+This short document aims to give a quick guide to anyone implementing API bindings for IPFS implementations-- in particular go-ipfs.\n+\n+Sections:\n+- IPFS Types\n+- API Transports\n+- API Commands\n+- Implementing bindings for the HTTP API\n+\n+## IPFS Types\n+\n+IPFS uses a set of type value that is useful to enumerate up front:\n+\n+- `<ipfs-path>` is unix-style path, beginning with `/ipfs/<hash>/...` or `/ipns/<hash>/...` or `/ipns/<domain>/...`.\n+- `<hash>` is a base58 encoded [multihash](https://github.com/jbenet/multihash) (there are [many implementations](https://github.com/jbenet/multihash#implementations)). Usually the hash of an ipfs object (or merkle dag node).\n+\n+A note on streams: IPFS is a streaming protocol. Everything about it can be streamed. When importing files, API requests should aim to stream the data in, and handle back-pressure correctly, so that the IPFS node can handle it sequentially without too much memory pressure. (If using HTTP, this is typically handled for you by writes to the request body blocking.)\n+\n+## API Transports\n+\n+Like with everything else, IPFS aims to be flexible regarding the API transports. Currently, the [go-ipfs](https://github.com/ipfs/go-ipfs) implementation supports both an in-process API and an HTTP api. More can be added easily, by mapping the API functions over a transport. (This is similar to how gRPC is also _mapped on top of transports_, like HTTP).\n+\n+Mapping to a transport involves leveraging the transport's features to express function calls. For example:\n+\n+### CLI API Transport\n+\n+In the commandline, IPFS uses a traditional flag and arg-based mapping, where:\n+- the first arguments selects the command, as in git - e.g. `ipfs object get`\n+- the flags specify options - e.g. `--enc=protobuf -q`\n+- the rest are positional arguments - e.g. `ipfs object patch <hash1> add-link foo <hash2>`\n+- files are specified by filename, or through stdin\n+\n+(NOTE: when go-ipfs runs the daemon, the CLI API is actually converted to HTTP calls. otherwise, they execute in the same process)\n+\n+### HTTP API Transport\n+\n+In HTTP, our API layering uses a REST-like mapping, where:\n+- the URL path selects the command - e.g `/object/get`\n+- the URL query string implements option arguments - e.g. `&enc=protobuf&q=true`\n+- the URL query also implements positional arguments - e.g. `&arg=<hash1>&arg=add-link&arg=foo&arg=<hash2>`\n+- the request body streams file data - reads files or stdin\n+  - multiple streams are muxed with multipart (todo: add tar stream support)\n+\n+\n+## API Commands\n+\n+There is a \"standard IPFS API\" with a set of commands, which we are documenting clearly soon. But this is not yet extracted into its own document. Perhaps -- as part of this API Bindings effort -- we can document it all. It is currently defined as \"all the commands exposed by the go-ipfs implementation\". You can see [a listing here](https://github.com/ipfs/go-ipfs/blob/916f987de2c35db71815b54bbb9a0a71df829838/core/commands/root.go#L82-L111), or by running `ipfs commands` locally. **The good news is: we should be able to easily write a program that outputs a markdown API specification!**\n+\n+(Note: the go-ipfs [commands library](https://github.com/ipfs/go-ipfs/tree/916f987de2c35db71815b54bbb9a0a71df829838/commands) also makes sure to keep the CLI and the HTTP API exactly in sync.)\n+\n+## Implementing bindings for the HTTP API\n+\n+As mentioned above, the API commands map to HTTP with:\n+- the URL path selects the command - e.g `/object/get`\n+- the URL query string implements option arguments - e.g. `&enc=protobuf&q=true`\n+- the URL query also implements positional arguments - e.g. `&arg=<hash1>&arg=add-link&arg=foo&arg=<hash2>`\n+- the request body streams file data - reads files or stdin\n+  - multiple streams are muxed with multipart (todo: add tar stream support)\n+\n+To date, we have two different HTTP API clients:\n+\n+- [node-ipfs-api](https://github.com/ipfs/node-ipfs-api) - simple javascript wrapper -- best to look at","path":"overviews/implement-api-bindings.md","position":null,"original_position":63,"commit_id":"45b5d5f40652ce01ee465df01bd4be6f372c2467","original_commit_id":"ea2cde0072efee442e3438de860ea69a8bff5357","user":{"login":"jbenet","id":138401,"avatar_url":"https://avatars.githubusercontent.com/u/138401?v=3","gravatar_id":"","url":"https://api.github.com/users/jbenet","html_url":"https://github.com/jbenet","followers_url":"https://api.github.com/users/jbenet/followers","following_url":"https://api.github.com/users/jbenet/following{/other_user}","gists_url":"https://api.github.com/users/jbenet/gists{/gist_id}","starred_url":"https://api.github.com/users/jbenet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jbenet/subscriptions","organizations_url":"https://api.github.com/users/jbenet/orgs","repos_url":"https://api.github.com/users/jbenet/repos","events_url":"https://api.github.com/users/jbenet/events{/privacy}","received_events_url":"https://api.github.com/users/jbenet/received_events","type":"User","site_admin":false},"body":"thanks addressed in 45b5d5f","created_at":"2015-11-23T06:36:06Z","updated_at":"2015-11-23T06:36:06Z","html_url":"https://github.com/ipfs/specs/pull/38#discussion_r45575190","pull_request_url":"https://api.github.com/repos/ipfs/specs/pulls/38","_links":{"self":{"href":"https://api.github.com/repos/ipfs/specs/pulls/comments/45575190"},"html":{"href":"https://github.com/ipfs/specs/pull/38#discussion_r45575190"},"pull_request":{"href":"https://api.github.com/repos/ipfs/specs/pulls/38"}}},"pull_request":{"url":"https://api.github.com/repos/ipfs/specs/pulls/38","id":50061087,"html_url":"https://github.com/ipfs/specs/pull/38","diff_url":"https://github.com/ipfs/specs/pull/38.diff","patch_url":"https://github.com/ipfs/specs/pull/38.patch","issue_url":"https://api.github.com/repos/ipfs/specs/issues/38","number":38,"state":"open","locked":false,"title":"Added some useful overviews","user":{"login":"jbenet","id":138401,"avatar_url":"https://avatars.githubusercontent.com/u/138401?v=3","gravatar_id":"","url":"https://api.github.com/users/jbenet","html_url":"https://github.com/jbenet","followers_url":"https://api.github.com/users/jbenet/followers","following_url":"https://api.github.com/users/jbenet/following{/other_user}","gists_url":"https://api.github.com/users/jbenet/gists{/gist_id}","starred_url":"https://api.github.com/users/jbenet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jbenet/subscriptions","organizations_url":"https://api.github.com/users/jbenet/orgs","repos_url":"https://api.github.com/users/jbenet/repos","events_url":"https://api.github.com/users/jbenet/events{/privacy}","received_events_url":"https://api.github.com/users/jbenet/received_events","type":"User","site_admin":false},"body":null,"created_at":"2015-11-08T14:14:53Z","updated_at":"2015-11-23T06:36:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7360c7f3036355d119b2cf92ca1cce9f9c4a1bfc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ipfs/specs/pulls/38/commits","review_comments_url":"https://api.github.com/repos/ipfs/specs/pulls/38/comments","review_comment_url":"https://api.github.com/repos/ipfs/specs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ipfs/specs/issues/38/comments","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/45b5d5f40652ce01ee465df01bd4be6f372c2467","head":{"label":"ipfs:overviews","ref":"overviews","sha":"45b5d5f40652ce01ee465df01bd4be6f372c2467","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":32023078,"name":"specs","full_name":"ipfs/specs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/specs","description":"Specs for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/specs","forks_url":"https://api.github.com/repos/ipfs/specs/forks","keys_url":"https://api.github.com/repos/ipfs/specs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/specs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/specs/teams","hooks_url":"https://api.github.com/repos/ipfs/specs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/specs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/specs/events","assignees_url":"https://api.github.com/repos/ipfs/specs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/specs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/specs/tags","blobs_url":"https://api.github.com/repos/ipfs/specs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/specs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/specs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/specs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/specs/languages","stargazers_url":"https://api.github.com/repos/ipfs/specs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/specs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/specs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/specs/subscription","commits_url":"https://api.github.com/repos/ipfs/specs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/specs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/specs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/specs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/specs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/specs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/specs/merges","archive_url":"https://api.github.com/repos/ipfs/specs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/specs/downloads","issues_url":"https://api.github.com/repos/ipfs/specs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/specs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/specs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/specs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/specs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/specs/releases{/id}","created_at":"2015-03-11T14:47:16Z","updated_at":"2015-11-22T23:13:07Z","pushed_at":"2015-11-23T06:35:54Z","git_url":"git://github.com/ipfs/specs.git","ssh_url":"git@github.com:ipfs/specs.git","clone_url":"https://github.com/ipfs/specs.git","svn_url":"https://github.com/ipfs/specs","homepage":"http://ipfs.io","size":10102,"stargazers_count":119,"watchers_count":119,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":21,"forks":13,"open_issues":21,"watchers":119,"default_branch":"master"}},"base":{"label":"ipfs:master","ref":"master","sha":"5c3c1a40a735f5ceef938c94472e3ee0920004ee","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":32023078,"name":"specs","full_name":"ipfs/specs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/specs","description":"Specs for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/specs","forks_url":"https://api.github.com/repos/ipfs/specs/forks","keys_url":"https://api.github.com/repos/ipfs/specs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/specs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/specs/teams","hooks_url":"https://api.github.com/repos/ipfs/specs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/specs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/specs/events","assignees_url":"https://api.github.com/repos/ipfs/specs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/specs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/specs/tags","blobs_url":"https://api.github.com/repos/ipfs/specs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/specs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/specs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/specs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/specs/languages","stargazers_url":"https://api.github.com/repos/ipfs/specs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/specs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/specs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/specs/subscription","commits_url":"https://api.github.com/repos/ipfs/specs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/specs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/specs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/specs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/specs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/specs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/specs/merges","archive_url":"https://api.github.com/repos/ipfs/specs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/specs/downloads","issues_url":"https://api.github.com/repos/ipfs/specs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/specs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/specs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/specs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/specs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/specs/releases{/id}","created_at":"2015-03-11T14:47:16Z","updated_at":"2015-11-22T23:13:07Z","pushed_at":"2015-11-23T06:35:54Z","git_url":"git://github.com/ipfs/specs.git","ssh_url":"git@github.com:ipfs/specs.git","clone_url":"https://github.com/ipfs/specs.git","svn_url":"https://github.com/ipfs/specs","homepage":"http://ipfs.io","size":10102,"stargazers_count":119,"watchers_count":119,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":21,"forks":13,"open_issues":21,"watchers":119,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ipfs/specs/pulls/38"},"html":{"href":"https://github.com/ipfs/specs/pull/38"},"issue":{"href":"https://api.github.com/repos/ipfs/specs/issues/38"},"comments":{"href":"https://api.github.com/repos/ipfs/specs/issues/38/comments"},"review_comments":{"href":"https://api.github.com/repos/ipfs/specs/pulls/38/comments"},"review_comment":{"href":"https://api.github.com/repos/ipfs/specs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ipfs/specs/pulls/38/commits"},"statuses":{"href":"https://api.github.com/repos/ipfs/specs/statuses/45b5d5f40652ce01ee465df01bd4be6f372c2467"}}}}