about summary refs log tree commit diff
diff options
context:
space:
mode:
authorfranck cuny <franck@lumberjaph.net>2010-11-17 11:51:18 +0100
committerfranck cuny <franck@lumberjaph.net>2010-11-17 11:51:18 +0100
commite03f48683b982f8b9efd4ca0dae0bd6bca7411b5 (patch)
tree552b892fb679ccd18f929e8a901b7f375c7a1ad5
parentadd format (diff)
parentspore2dot: split note & doc (diff)
downloadapi-description-e03f48683b982f8b9efd4ca0dae0bd6bca7411b5.tar.gz
Merge branch 'master' of github.com:SPORE/api-description
* 'master' of github.com:SPORE/api-description:
  spore2dot: split note & doc
  add modularized CouchDB
  spore2dot: add note
  Ohloh: typo
  add the Ohloh API, http://www.ohloh.net
  CouchDB: an alternate description (still incomplete)
  spore2dot: add a detailed generation
  Github: rename some methods s/^get_/list_/;
  Github/network: missing params
-rw-r--r--apps/Makefile3
-rw-r--r--apps/couchdb/Makefile29
-rw-r--r--apps/couchdb/couchdb.pngbin0 -> 261335 bytes
-rw-r--r--apps/couchdb/database.json147
-rw-r--r--apps/couchdb/design.json142
-rw-r--r--apps/couchdb/document.json155
-rw-r--r--apps/couchdb/server.json86
-rw-r--r--services/Makefile2
-rw-r--r--services/github.json62
-rw-r--r--services/github.pngbin199198 -> 192731 bytes
-rw-r--r--services/github/commit.json6
-rw-r--r--services/github/gist.json4
-rw-r--r--services/github/github.pngbin195024 -> 196502 bytes
-rw-r--r--services/github/issue.json10
-rw-r--r--services/github/network.json8
-rw-r--r--services/github/object.json10
-rw-r--r--services/github/repository.json24
-rw-r--r--services/github/user.json12
-rw-r--r--services/ohloh.json292
-rw-r--r--services/ohloh.pngbin0 -> 85913 bytes
-rw-r--r--utils/spore2dot.pl42
21 files changed, 969 insertions, 65 deletions
diff --git a/apps/Makefile b/apps/Makefile
index a9a6a72..52a1661 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -3,6 +3,7 @@ VALIDATOR := perl ../utils/validator.pl --schema spore_validation.rx --descripti
 SPORE2DOT := perl ../utils/spore2dot.pl
 
 check: spore_validation.rx
+	@make -C couchdb check
 	@$(VALIDATOR) couchdb.json
 	@$(VALIDATOR) presque.json
 
@@ -14,6 +15,7 @@ spore_validation.rx:
 png: \
     couchdb.png \
     presque.png
+	@make -C couchdb png
 
 %.png : %.dot
 	dot -T png -o $@ $<
@@ -22,4 +24,5 @@ png: \
 	$(SPORE2DOT) $< > $@
 
 clean:
+	@make -C couchdb clean
 	-rm *.png *.dot spore_validation.rx
diff --git a/apps/couchdb/Makefile b/apps/couchdb/Makefile
new file mode 100644
index 0000000..a8177ca
--- /dev/null
+++ b/apps/couchdb/Makefile
@@ -0,0 +1,29 @@
+
+VALIDATOR := perl ../../utils/validator.pl --schema spore_validation.rx --description
+SPORE2DOT := perl ../../utils/spore2dot.pl
+
+check: spore_validation.rx
+	@$(VALIDATOR) server.json
+	@$(VALIDATOR) database.json
+	@$(VALIDATOR) document.json
+	@$(VALIDATOR) design.json
+
+test: check
+
+spore_validation.rx:
+	wget http://github.com/SPORE/specifications/raw/master/spore_validation.rx
+
+png: couchdb.png
+
+%.png : %.dot
+	dot -T png -o $@ $<
+
+couchdb.dot: \
+    server.json \
+    database.json \
+    document.json \
+    design.json
+	$(SPORE2DOT) $^ > $@
+
+clean:
+	-rm *.png *.dot spore_validation.rx
diff --git a/apps/couchdb/couchdb.png b/apps/couchdb/couchdb.png
new file mode 100644
index 0000000..41379cf
--- /dev/null
+++ b/apps/couchdb/couchdb.png
Binary files differdiff --git a/apps/couchdb/database.json b/apps/couchdb/database.json
new file mode 100644
index 0000000..080b148
--- /dev/null
+++ b/apps/couchdb/database.json
@@ -0,0 +1,147 @@
+{
+   "version" : "0.1",
+   "methods" : {
+      "get_info" : {
+         "path" : "/:db",
+         "method" : "GET",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "create_db" : {
+         "path" : "/:db",
+         "method" : "PUT",
+         "required_params" : [
+            "db"
+         ],
+         "expected_status" : [ 201, 412 ]
+      },
+      "delete_db" : {
+         "path" : "/:db",
+         "method" : "DELETE",
+         "required_params" : [
+            "db"
+         ],
+         "expected_status" : [ 200, 404 ]
+      },
+      "get_changes" : {
+         "path" : "/:db/_changes",
+         "method" : "GET",
+         "required_params" : [
+            "db"
+         ],
+         "optional_params" : [
+            "feed",
+            "filter",
+            "heartbeat",
+            "since",
+            "style"
+         ],
+         "unattended_params" : true
+      },
+      "compact" : {
+         "path" : "/:db/_compact",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ],
+         "expected_status" : [ 202 ]
+      },
+      "compact_design" : {
+         "path" : "/:db/_compact/design-doc",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ],
+         "expected_status" : [ 202 ]
+      },
+      "clean_view" : {
+         "path" : "/:db/_view_cleanup",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "execute_view" : {
+         "path" : "/:db/_temp_view",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "ensure_full_commit" : {
+         "path" : "/:db/_ensure_full_commit",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "bulk_docs" : {
+         "path" : "/:db/_bulk_docs",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "purge" : {
+         "path" : "/:db/_purge",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "get_all_docs" : {
+         "path" : "/:db/_all_docs",
+         "method" : "GET",
+         "required_params" : [
+            "db"
+         ],
+         "optional_params" : [
+            "descending",
+            "startkey",
+            "endkey",
+            "limit"
+         ]
+      },
+      "get_security" : {
+         "path" : "/:db/_security",
+         "method" : "GET",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "set_security" : {
+         "path" : "/:db/_security",
+         "method" : "PUT",
+         "required_params" : [
+            "db"
+         ],
+         "required_payload" : true
+      },
+      "get_revs_limit" : {
+         "path" : "/:db/_revs_limit",
+         "method" : "GET",
+         "required_params" : [
+            "db"
+         ]
+      },
+      "set_revs_limit" : {
+         "path" : "/:db/_revs_limit",
+         "method" : "PUT",
+         "required_params" : [
+            "db"
+         ],
+         "required_payload" : true
+      }
+   },
+   "formats" : [
+      "json"
+   ],
+   "expected_status" : [ 200 ],
+   "name" : "CouchDB",
+   "authority" : "http://github.com/SPORE",
+   "meta" : {
+      "documentation" : "http://wiki.apache.org/couchdb/Complete_HTTP_API_Reference",
+      "module" : "database"
+   }
+}
diff --git a/apps/couchdb/design.json b/apps/couchdb/design.json
new file mode 100644
index 0000000..0b1cc51
--- /dev/null
+++ b/apps/couchdb/design.json
@@ -0,0 +1,142 @@
+{
+   "version" : "0.1",
+   "methods" : {
+      "get_design" : {
+         "path" : "/:db/_design/:design",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design"
+         ],
+         "optional_params" : [
+            "rev",
+            "revs"
+         ]
+      },
+      "add_design" : {
+         "path" : "/:db/_design/:design",
+         "method" : "PUT",
+         "required_params" : [
+            "db",
+            "design"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "delete_design" : {
+         "path" : "/:db/_design/:design",
+         "method" : "DELETE",
+         "required_params" : [
+            "db",
+            "design",
+            "rev"
+         ]
+      },
+      "copy_design" : {
+         "path" : "/:db/_design/:design",
+         "method" : "COPY",
+         "headers" : {
+            "Destination" : ":dest"
+         },
+         "required_params" : [
+            "db",
+            "design",
+            "dest"
+         ],
+         "optional_params" : [
+            "rev"
+         ],
+         "expected_status" : [ 201 ]
+      },
+      "get_design_attachment" : {
+         "path" : "/:db/_design/:design/:file",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design",
+            "file"
+         ]
+      },
+      "add_design_attachment" : {
+         "path" : "/:db/_design/:design/:file",
+         "method" : "PUT",
+         "required_params" : [
+            "db",
+            "design",
+            "file"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "delete_design_attachment" : {
+         "path" : "/:db/_design/:design/:file",
+         "method" : "DELETE",
+         "required_params" : [
+            "db",
+            "design",
+            "file"
+         ],
+         "expected_status" : [ 200, 409 ]
+      },
+      "get_design_info" : {
+         "path" : "/:db/_design/:design/_info",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design"
+         ]
+      },
+      "get_view" : {
+         "path" : "/:db/_design/:design/_view/:view",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design",
+            "view"
+         ]
+      },
+      "get_show_without_doc" : {
+         "path" : "/:db/_design/:design/_show/:show",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design",
+            "show"
+         ],
+         "unattended_params" : true
+      },
+      "get_show" : {
+         "path" : "/:db/_design/:design/_show/:show/:id",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design",
+            "show",
+            "id"
+         ],
+         "unattended_params" : true
+      },
+      "get_list" : {
+         "path" : "/:db/_design/:design/_list/:list/:view",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "design",
+            "list",
+            "view"
+         ],
+         "unattended_params" : true
+      }
+   },
+   "expected_status" : [ 200, 404 ],
+   "formats" : [
+      "json"
+   ],
+   "name" : "CouchDB",
+   "authority" : "http://github.com/SPORE",
+   "meta" : {
+      "documentation" : "http://wiki.apache.org/couchdb/Complete_HTTP_API_Reference",
+      "module" : "design",
+      "enable_if" : "get_design_attachment"
+   }
+}
diff --git a/apps/couchdb/document.json b/apps/couchdb/document.json
new file mode 100644
index 0000000..12e5afb
--- /dev/null
+++ b/apps/couchdb/document.json
@@ -0,0 +1,155 @@
+{
+   "version" : "0.1",
+   "methods" : {
+      "insert_document" : {
+         "path" : "/:db",
+         "method" : "POST",
+         "required_params" : [
+            "db"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "get_document" : {
+         "path" : "/:db/:id",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "id"
+         ],
+         "optional_params" : [
+            "rev",
+            "revs"
+         ]
+      },
+      "add_document" : {
+         "path" : "/:db/:id",
+         "method" : "PUT",
+         "required_params" : [
+            "db",
+            "id"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "delete_document" : {
+         "path" : "/:db/:id",
+         "method" : "DELETE",
+         "required_params" : [
+            "db",
+            "id",
+            "rev"
+         ],
+         "expected_status" : [ 200, 409 ]
+      },
+      "copy_document" : {
+         "path" : "/:db/:id",
+         "method" : "COPY",
+         "headers" : {
+            "Destination" : ":dest"
+         },
+         "required_params" : [
+            "db",
+            "id",
+            "dest"
+         ],
+         "optional_params" : [
+            "rev"
+         ],
+         "expected_status" : [ 201 ]
+      },
+      "get_attachment" : {
+         "path" : "/:db/:id/:file",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "id",
+            "file"
+         ]
+      },
+      "add_attachment" : {
+         "path" : "/:db/:id/:file",
+         "method" : "PUT",
+         "headers" : {
+            "Content-Type" : ":content_type"
+         },
+         "required_params" : [
+            "db",
+            "id",
+            "rev",
+            "file",
+            "content_type"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "delete_attachment" : {
+         "path" : "/:db/:id/:file",
+         "method" : "DELETE",
+         "required_params" : [
+            "db",
+            "id",
+            "file"
+         ]
+      },
+      "get_local_document" : {
+         "path" : "/:db/_local/:id",
+         "method" : "GET",
+         "required_params" : [
+            "db",
+            "id"
+         ],
+         "optional_params" : [
+            "rev",
+            "revs"
+         ]
+      },
+      "add_local_document" : {
+         "path" : "/:db/_local/:id",
+         "method" : "PUT",
+         "required_params" : [
+            "db",
+            "id"
+         ],
+         "required_payload" : true,
+         "expected_status" : [ 201, 409 ]
+      },
+      "delete_local_document" : {
+         "path" : "/:db/_local/:id",
+         "method" : "DELETE",
+         "required_params" : [
+            "db",
+            "id",
+            "rev"
+         ],
+         "expected_status" : [ 200, 409 ]
+      },
+      "copy_local_document" : {
+         "path" : "/:db/_local/:id",
+         "method" : "COPY",
+         "headers" : {
+            "Destination" : ":dest"
+         },
+         "required_params" : [
+            "db",
+            "id",
+            "dest"
+         ],
+         "optional_params" : [
+            "rev"
+         ],
+         "expected_status" : [ 201 ]
+      }
+   },
+   "formats" : [
+      "json"
+   ],
+   "expected_status" : [ 200, 404 ],
+   "name" : "CouchDB",
+   "authority" : "http://github.com/SPORE",
+   "meta" : {
+      "documentation" : "http://wiki.apache.org/couchdb/Complete_HTTP_API_Reference",
+      "module" : "document",
+      "enable_if" : "get_attachment"
+   }
+}
diff --git a/apps/couchdb/server.json b/apps/couchdb/server.json
new file mode 100644
index 0000000..3f59827
--- /dev/null
+++ b/apps/couchdb/server.json
@@ -0,0 +1,86 @@
+{
+   "version" : "0.1",
+   "methods" : {
+      "get_root" : {
+         "path" : "/",
+         "method" : "GET"
+      },
+      "get_all_dbs" : {
+         "path" : "/_all_dbs",
+         "method" : "GET"
+      },
+      "get_active_tasks" : {
+         "path" : "/_active_tasks",
+         "method" : "GET"
+      },
+      "replicate" : {
+         "path" : "/_replicate",
+         "method" : "POST",
+         "required_payload" : true
+      },
+      "get_uuids" : {
+         "path" : "/_uuids",
+         "method" : "GET",
+         "optional_params" : [
+            "count"
+         ]
+      },
+      "restart" : {
+         "path" : "/_restart",
+         "method" : "POST"
+      },
+      "get_stats" : {
+         "path" : "/_stats",
+         "method" : "GET"
+      },
+      "get_log" : {
+         "path" : "/_log",
+         "method" : "GET"
+      },
+      "get_config" : {
+         "path" : "/_config",
+         "method" : "GET"
+      },
+      "get_config_section" : {
+         "path" : "/_config/:section",
+         "method" : "GET",
+         "required_params" : [
+            "section"
+         ]
+      },
+      "get_config_item" : {
+         "path" : "/_config/:section/:key",
+         "method" : "GET",
+         "required_params" : [
+            "section",
+            "key"
+         ]
+      },
+      "set_config_item" : {
+         "path" : "/_config/:section/:key",
+         "method" : "PUT",
+         "required_params" : [
+            "section",
+            "key"
+         ]
+      },
+      "delete_config_item" : {
+         "path" : "/_config/:section/:key",
+         "method" : "DELETE",
+         "required_params" : [
+            "section",
+            "key"
+         ]
+      }
+   },
+   "formats" : [
+      "json"
+   ],
+   "expected_status" : [ 200 ],
+   "name" : "CouchDB",
+   "authority" : "http://github.com/SPORE",
+   "meta" : {
+      "documentation" : "http://wiki.apache.org/couchdb/Complete_HTTP_API_Reference",
+      "module" : "server"
+   }
+}
diff --git a/services/Makefile b/services/Makefile
index 0e0835f..dbca662 100644
--- a/services/Makefile
+++ b/services/Makefile
@@ -7,6 +7,7 @@ check: spore_validation.rx
 	@$(VALIDATOR) backtype.json
 	@$(VALIDATOR) github.json
 	@$(VALIDATOR) ihackernews.json
+	@$(VALIDATOR) ohloh.json
 	@$(VALIDATOR) twitter.json
 
 test: check
@@ -19,6 +20,7 @@ png: \
     backtype.png \
     github.png \
     ihackernews.png \
+    ohloh.png \
     twitter.png
 	@make -C github png
 
diff --git a/services/github.json b/services/github.json
index 66c1369..a58481a 100644
--- a/services/github.json
+++ b/services/github.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "user_search" : {
          "path" : "/:format/user/search/:search",
@@ -49,7 +49,7 @@
          ],
          "authentication" : true
       },
-      "get_following" : {
+      "list_following" : {
          "path" : "/:format/user/show/:user/following",
          "method" : "GET",
          "required_params" : [
@@ -57,7 +57,7 @@
             "user"
          ]
       },
-      "get_followers" : {
+      "list_followers" : {
          "path" : "/:format/user/show/:user/followers",
          "method" : "GET",
          "required_params" : [
@@ -83,7 +83,7 @@
          ],
          "authentication" : true
       },
-      "get_watched_repos" : {
+      "list_watched_repos" : {
          "path" : "/:format/repos/watched/:user",
          "method" : "GET",
          "required_params" : [
@@ -91,7 +91,7 @@
             "user"
          ]
       },
-      "get_keys" : {
+      "list_keys" : {
          "path" : "/:format/user/keys",
          "method" : "GET",
          "required_params" : [
@@ -125,7 +125,7 @@
          ],
          "authentication" : true
       },
-      "get_emails" : {
+      "list_emails" : {
          "path" : "/:format/user/emails",
          "method" : "GET",
          "required_params" : [
@@ -169,7 +169,7 @@
             "search_term"
          ]
       },
-      "get_issues" : {
+      "list_issues" : {
          "path" : "/:format/issues/list/:user/:repo/:state",
          "method" : "GET",
          "required_params" : [
@@ -179,7 +179,7 @@
             "state"
          ]
       },
-      "get_issues_by_label" : {
+      "list_issues_by_label" : {
          "path" : "/:format/issues/list/:user/:repo/label/:label",
          "method" : "GET",
          "required_params" : [
@@ -199,7 +199,7 @@
             "number"
          ]
       },
-      "get_comments" : {
+      "list_comments" : {
          "path" : "/:format/issues/comments/:user/:repo/:number",
          "method" : "GET",
          "required_params" : [
@@ -268,7 +268,7 @@
          ],
          "authentication" : true
       },
-      "get_labels" : {
+      "list_labels" : {
          "path" : "/:format/issues/labels/:user/:repo",
          "method" : "GET",
          "required_params" : [
@@ -335,7 +335,7 @@
             "filename"
          ]
       },
-      "get_gists" : {
+      "list_gists" : {
          "base_url" : "http://gist.github.com/api/v1/",
          "path" : "/:format/gists/:login",
          "method" : "GET",
@@ -353,13 +353,17 @@
             "repo"
          ]
       },
-      "get_network_data" : {
+      "list_network_data" : {
          "path" : "/:user/:repo/network_data_chunk",
          "method" : "GET",
          "required_params" : [
             "user",
             "repo",
             "nethash"
+         ],
+         "optional_params" : [
+            "start",
+            "end"
          ]
       },
 
@@ -408,7 +412,7 @@
          ],
          "authentication" : true
       },
-      "get_repos" : {
+      "list_repos" : {
          "path" : "/:format/repos/show/:user",
          "method" : "GET",
          "required_params" : [
@@ -496,7 +500,7 @@
          ],
          "authentication" : true
       },
-      "get_repo_keys" : {
+      "list_repo_keys" : {
          "path" : "/:format/repos/keys/:user/:repo",
          "method" : "GET",
          "required_params" : [
@@ -536,7 +540,7 @@
          ],
          "authentication" : true
       },
-      "get_collaborators" : {
+      "list_collaborators" : {
          "path" : "/:format/repos/show/:user/:repo/collaborators",
          "method" : "GET",
          "required_params" : [
@@ -568,7 +572,7 @@
          ],
          "authentication" : true
       },
-      "get_pushable" : {
+      "list_pushable" : {
          "path" : "/:format/repos/pushable",
          "method" : "GET",
          "required_params" : [
@@ -576,7 +580,7 @@
          ],
          "authentication" : true
       },
-      "get_contributors" : {
+      "list_contributors" : {
          "path" : "/:format/repos/show/:user/:repo/contributors",
          "method" : "GET",
          "required_params" : [
@@ -585,7 +589,7 @@
             "repo"
          ]
       },
-      "get_anon_contributors" : {
+      "list_anon_contributors" : {
          "path" : "/:format/repos/show/:user/:repo/contributors/anon",
          "method" : "GET",
          "required_params" : [
@@ -594,7 +598,7 @@
             "repo"
          ]
       },
-      "get_watchers" : {
+      "list_watchers" : {
          "path" : "/:format/repos/show/:user/:repo/watchers",
          "method" : "GET",
          "required_params" : [
@@ -603,7 +607,7 @@
             "repo"
          ]
       },
-      "get_network" : {
+      "list_network" : {
          "path" : "/:format/repos/show/:user/:repo/network",
          "method" : "GET",
          "required_params" : [
@@ -612,7 +616,7 @@
             "repo"
          ]
       },
-      "get_languages" : {
+      "list_languages" : {
          "path" : "/:format/repos/show/:user/:repo/languages",
          "method" : "GET",
          "required_params" : [
@@ -621,7 +625,7 @@
             "repo"
          ]
       },
-      "get_tags" : {
+      "list_tags" : {
          "path" : "/:format/repos/show/:user/:repo/tags",
          "method" : "GET",
          "required_params" : [
@@ -630,7 +634,7 @@
             "repo"
          ]
       },
-      "get_branches" : {
+      "list_branches" : {
          "path" : "/:format/repos/show/:user/:repo/branches",
          "method" : "GET",
          "required_params" : [
@@ -640,7 +644,7 @@
          ]
       },
 
-      "get_commits" : {
+      "list_commits" : {
          "path" : "/:format/commits/list/:user/:repo/:branch",
          "method" : "GET",
          "required_params" : [
@@ -650,7 +654,7 @@
             "branch"
          ]
       },
-      "get_file_commits" : {
+      "list_file_commits" : {
          "path" : "/:format/commits/list/:user/:repo/:branch/:path",
          "method" : "GET",
          "required_params" : [
@@ -672,7 +676,7 @@
          ]
       },
 
-      "get_tree" : {
+      "list_tree" : {
          "path" : "/:format/tree/show/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -696,7 +700,7 @@
             "meta"
          ]
       },
-      "get_blobs" : {
+      "list_blobs" : {
          "path" : "/:format/blob/all/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -706,7 +710,7 @@
             "sha"
          ]
       },
-      "get_full_blobs" : {
+      "list_full_blobs" : {
          "path" : "/:format/blob/full/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -716,7 +720,7 @@
             "tree_sha"
          ]
       },
-      "get_full_tree" : {
+      "list_full_tree" : {
          "path" : "/:format/tree/full/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github.png b/services/github.png
index 96ff922..d128b2c 100644
--- a/services/github.png
+++ b/services/github.png
Binary files differdiff --git a/services/github/commit.json b/services/github/commit.json
index 8fe4823..3abd9e8 100644
--- a/services/github/commit.json
+++ b/services/github/commit.json
@@ -1,8 +1,8 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
-      "get_commits" : {
+      "list_commits" : {
          "path" : "/:format/commits/list/:user/:repo/:branch",
          "method" : "GET",
          "required_params" : [
@@ -12,7 +12,7 @@
             "branch"
          ]
       },
-      "get_file_commits" : {
+      "list_file_commits" : {
          "path" : "/:format/commits/list/:user/:repo/:branch/:path",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github/gist.json b/services/github/gist.json
index c10949f..3cc7614 100644
--- a/services/github/gist.json
+++ b/services/github/gist.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://gist.github.com/api/v1/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "get_gist_info" : {
          "path" : "/:format/:gist_id",
@@ -19,7 +19,7 @@
             "filename"
          ]
       },
-      "get_gists" : {
+      "list_gists" : {
          "path" : "/:format/gists/:login",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github/github.png b/services/github/github.png
index 1d2b070..103c83e 100644
--- a/services/github/github.png
+++ b/services/github/github.png
Binary files differdiff --git a/services/github/issue.json b/services/github/issue.json
index f574c01..e269a24 100644
--- a/services/github/issue.json
+++ b/services/github/issue.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "issue_search" : {
          "path" : "/:format/issues/search/:user/:repo/:state/:search_term",
@@ -13,7 +13,7 @@
             "search_term"
          ]
       },
-      "get_issues" : {
+      "list_issues" : {
          "path" : "/:format/issues/list/:user/:repo/:state",
          "method" : "GET",
          "required_params" : [
@@ -23,7 +23,7 @@
             "state"
          ]
       },
-      "get_issues_by_label" : {
+      "list_issues_by_label" : {
          "path" : "/:format/issues/list/:user/:repo/label/:label",
          "method" : "GET",
          "required_params" : [
@@ -43,7 +43,7 @@
             "number"
          ]
       },
-      "get_comments" : {
+      "list_comments" : {
          "path" : "/:format/issues/comments/:user/:repo/:number",
          "method" : "GET",
          "required_params" : [
@@ -112,7 +112,7 @@
          ],
          "authentication" : true
       },
-      "get_labels" : {
+      "list_labels" : {
          "path" : "/:format/issues/labels/:user/:repo",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github/network.json b/services/github/network.json
index 2833783..bb8792d 100644
--- a/services/github/network.json
+++ b/services/github/network.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "get_network_meta" : {
          "path" : "/:user/:repo/network_meta",
@@ -10,13 +10,17 @@
             "repo"
          ]
       },
-      "get_network_data" : {
+      "list_network_data" : {
          "path" : "/:user/:repo/network_data_chunk",
          "method" : "GET",
          "required_params" : [
             "user",
             "repo",
             "nethash"
+         ],
+         "optional_params" : [
+            "start",
+            "end"
          ]
       }
    },
diff --git a/services/github/object.json b/services/github/object.json
index 8891242..08ece21 100644
--- a/services/github/object.json
+++ b/services/github/object.json
@@ -1,8 +1,8 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
-      "get_tree" : {
+      "list_tree" : {
          "path" : "/:format/tree/show/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -26,7 +26,7 @@
             "meta"
          ]
       },
-      "get_blobs" : {
+      "list_blobs" : {
          "path" : "/:format/blob/all/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -36,7 +36,7 @@
             "sha"
          ]
       },
-      "get_full_blobs" : {
+      "list_full_blobs" : {
          "path" : "/:format/blob/full/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
@@ -46,7 +46,7 @@
             "tree_sha"
          ]
       },
-      "get_full_tree" : {
+      "list_full_tree" : {
          "path" : "/:format/tree/full/:user/:repo/:tree_sha",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github/repository.json b/services/github/repository.json
index 85c5246..d106c56 100644
--- a/services/github/repository.json
+++ b/services/github/repository.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "repo_search" : {
          "path" : "/:format/repos/search/:q",
@@ -47,7 +47,7 @@
          ],
          "authentication" : true
       },
-      "get_repos" : {
+      "list_repos" : {
          "path" : "/:format/repos/show/:user",
          "method" : "GET",
          "required_params" : [
@@ -135,7 +135,7 @@
          ],
          "authentication" : true
       },
-      "get_repo_keys" : {
+      "list_repo_keys" : {
          "path" : "/:format/repos/keys/:user/:repo",
          "method" : "GET",
          "required_params" : [
@@ -175,7 +175,7 @@
          ],
          "authentication" : true
       },
-      "get_collaborators" : {
+      "list_collaborators" : {
          "path" : "/:format/repos/show/:user/:repo/collaborators",
          "method" : "GET",
          "required_params" : [
@@ -207,7 +207,7 @@
          ],
          "authentication" : true
       },
-      "get_pushable" : {
+      "list_pushable" : {
          "path" : "/:format/repos/pushable",
          "method" : "GET",
          "required_params" : [
@@ -215,7 +215,7 @@
          ],
          "authentication" : true
       },
-      "get_contributors" : {
+      "list_contributors" : {
          "path" : "/:format/repos/show/:user/:repo/contributors",
          "method" : "GET",
          "required_params" : [
@@ -224,7 +224,7 @@
             "repo"
          ]
       },
-      "get_anon_contributors" : {
+      "list_anon_contributors" : {
          "path" : "/:format/repos/show/:user/:repo/contributors/anon",
          "method" : "GET",
          "required_params" : [
@@ -233,7 +233,7 @@
             "repo"
          ]
       },
-      "get_watchers" : {
+      "list_watchers" : {
          "path" : "/:format/repos/show/:user/:repo/watchers",
          "method" : "GET",
          "required_params" : [
@@ -242,7 +242,7 @@
             "repo"
          ]
       },
-      "get_network" : {
+      "list_network" : {
          "path" : "/:format/repos/show/:user/:repo/network",
          "method" : "GET",
          "required_params" : [
@@ -251,7 +251,7 @@
             "repo"
          ]
       },
-      "get_languages" : {
+      "list_languages" : {
          "path" : "/:format/repos/show/:user/:repo/languages",
          "method" : "GET",
          "required_params" : [
@@ -260,7 +260,7 @@
             "repo"
          ]
       },
-      "get_tags" : {
+      "list_tags" : {
          "path" : "/:format/repos/show/:user/:repo/tags",
          "method" : "GET",
          "required_params" : [
@@ -269,7 +269,7 @@
             "repo"
          ]
       },
-      "get_branches" : {
+      "list_branches" : {
          "path" : "/:format/repos/show/:user/:repo/branches",
          "method" : "GET",
          "required_params" : [
diff --git a/services/github/user.json b/services/github/user.json
index 60a1875..5f5399e 100644
--- a/services/github/user.json
+++ b/services/github/user.json
@@ -1,6 +1,6 @@
 {
    "base_url" : "http://github.com/api/v2/",
-   "version" : "0.3",
+   "version" : "0.4",
    "methods" : {
       "user_search" : {
          "path" : "/:format/user/search/:search",
@@ -49,7 +49,7 @@
          ],
          "authentication" : true
       },
-      "get_following" : {
+      "list_following" : {
          "path" : "/:format/user/show/:user/following",
          "method" : "GET",
          "required_params" : [
@@ -57,7 +57,7 @@
             "user"
          ]
       },
-      "get_followers" : {
+      "list_followers" : {
          "path" : "/:format/user/show/:user/followers",
          "method" : "GET",
          "required_params" : [
@@ -83,7 +83,7 @@
          ],
          "authentication" : true
       },
-      "get_watched_repos" : {
+      "list_watched_repos" : {
          "path" : "/:format/repos/watched/:user",
          "method" : "GET",
          "required_params" : [
@@ -91,7 +91,7 @@
             "user"
          ]
       },
-      "get_keys" : {
+      "list_keys" : {
          "path" : "/:format/user/keys",
          "method" : "GET",
          "required_params" : [
@@ -125,7 +125,7 @@
          ],
          "authentication" : true
       },
-      "get_emails" : {
+      "list_emails" : {
          "path" : "/:format/user/emails",
          "method" : "GET",
          "required_params" : [
diff --git a/services/ohloh.json b/services/ohloh.json
new file mode 100644
index 0000000..9152586
--- /dev/null
+++ b/services/ohloh.json
@@ -0,0 +1,292 @@
+{
+   "name" : "Ohloh",
+   "version" : "0.1",
+   "base_url" : "http://www.ohloh.net",
+   "methods" : {
+      "get_account" : {
+         "path" : "/accounts/:account_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+      "list_accounts" : {
+         "path" : "/accounts.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key"
+         ],
+         "optional_params" : [
+            "query",
+            "sort",
+            "page"
+         ]
+      },
+
+      "list_activity_facts" : {
+         "path" : "/projects/:project_id/analyses/:analysis_id/activity_facts.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "analysis_id"
+         ]
+      },
+      "list_latest_activity_facts" : {
+         "path" : "/projects/:project_id/analyses/latest/activity_facts.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+
+      "get_analysis" : {
+         "path" : "/projects/:project_id/analyses/:analysis_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "analysis_id"
+         ]
+      },
+      "get_latest_analysis" : {
+         "path" : "/projects/:project_id/analyses/latest.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+
+      "get_contributor_fact" : {
+         "path" : "/projects/:project_id/contributors/:contributor_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "contributor_id"
+         ]
+      },
+      "list_contributor_facts" : {
+         "path" : "/projects/:project_id/contributors.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+
+      "list_contributor_language_facts" : {
+         "path" : "/projects/:project_id/contributors/:contributor_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "contributor_id"
+         ]
+      },
+
+      "get_enlistment" : {
+         "path" : "projects/:project_id/enlistment/:enlistment_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "enlistment_id"
+         ]
+      },
+      "list_enlistments" : {
+         "path" : "projects/:project_id/enlistments.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ],
+         "optional_params" : [
+            "query",
+            "sort",
+            "page"
+         ]
+      },
+
+      "get_factoid" : {
+         "path" : "projects/:project_id/factoids/:factoid_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "factoid_id"
+         ]
+      },
+      "list_factoids" : {
+         "path" : "projects/:project_id/factoids.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+
+      "list_kudos" : {
+         "path" : "/accounts/:account_id/kudos.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+      "list_kudos_sent" : {
+         "path" : "/accounts/:account_id/kudos/sent.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+
+      "get_language" : {
+         "path" : "/languages/:language_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "language_id"
+         ]
+      },
+      "list_languages" : {
+         "path" : "/languages.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key"
+         ],
+         "optional_params" : [
+            "query",
+            "sort",
+            "page"
+         ]
+      },
+
+      "get_message" : {
+         "path" : "/accounts/:account_id/messages/:message_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id",
+            "message_id"
+         ]
+      },
+      "list_messages_by_account" : {
+         "path" : "/accounts/:account_id/messages.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+      "list_messages_by_project" : {
+         "path" : "/projects/:project_id/messages.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+      "create_message" : {
+         "path" : "/accounts/me/messages.xml",
+         "method" : "POST",
+         "form-data" : {
+            "message[body]" : ":body"
+         },
+         "required_params" : [
+            "body"
+         ],
+         "authentication" : true
+      },
+
+      "list_news" : {
+         "path" : "/accounts/:account_id/news.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+
+      "get_project" : {
+         "path" : "/projects/:project_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+      "list_projects" : {
+         "path" : "/projects.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key"
+         ],
+         "optional_params" : [
+            "query",
+            "sort",
+            "page"
+         ]
+      },
+
+      "list_size_facts" : {
+         "path" : "/projects/:project_id/analyses/:analysis_id/size_facts.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id",
+            "analysis_id"
+         ]
+      },
+      "list_latest_size_facts" : {
+         "path" : "/projects/:project_id/analyses/latest/size_facts.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ]
+      },
+
+      "get_stack" : {
+         "path" : "/accounts/:account_id/stacks/:stack_id.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id",
+            "stack_id"
+         ]
+      },
+      "get_default_stack" : {
+         "path" : "/accounts/:account_id/stacks/default.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "account_id"
+         ]
+      },
+      "list_stacks" : {
+         "path" : "/projects/:project_id/stacks.xml",
+         "method" : "GET",
+         "required_params" : [
+            "api_key",
+            "project_id"
+         ],
+         "optional_params" : [
+            "query",
+            "sort",
+            "page"
+         ]
+      }
+   },
+   "expected_status" : [ 200, 400 ],
+   "formats" : [ "xml" ],
+   "authority" : "http://github.com/SPORE",
+   "meta" : {
+      "documentation" : "http://www.ohloh.net/api/getting_started"
+   }
+}
diff --git a/services/ohloh.png b/services/ohloh.png
new file mode 100644
index 0000000..3fdef1b
--- /dev/null
+++ b/services/ohloh.png
Binary files differdiff --git a/utils/spore2dot.pl b/utils/spore2dot.pl
index 034e8c7..f7e0e7e 100644
--- a/utils/spore2dot.pl
+++ b/utils/spore2dot.pl
@@ -65,12 +65,52 @@ foreach my $spec (@specs) {
             print $_, "\\]";
             $first = 0;
         }
+        if ($desc->{optional_payload}) {
+            print "\\[";
+            print ", " unless $first;
+            print "payload\\]";
+            $first = 0;
+        }
+        if ($desc->{unattended_params} || $spec->{unattended_params}) {
+            print ", " unless $first;
+            print "...";
+        }
         print ")";
         print " &otimes;" if $desc->{authentication} || $spec->{authentication};
+        print " DEPRECATED" if $desc->{deprecated};
         print "\\l";
-        print "&nbsp;&nbsp;&nbsp;", $desc->{method}, " ", $desc->{path}, "\\l" if $ENV{SPORE_PATH};
+        if ($ENV{SPORE_DETAILS}) {
+            print "&nbsp;&nbsp;&nbsp;", $desc->{method}, " ", $desc->{path}, "\\l";
+            for my $h (sort keys %{$desc->{headers}}) {
+                print "&nbsp;&nbsp;&nbsp;", $h, ": ", $desc->{headers}->{$h}, "\\l";
+            }
+            for my $f (sort keys %{$desc->{'form-data'}}) {
+                print "&nbsp;&nbsp;&nbsp;form-data \\\"", $f, "\\\" ", $desc->{'form-data'}->{$f}, "\\l";
+            }
+            my $status = $desc->{expected_status} || $spec->{expected_status};
+            print "&nbsp;&nbsp;&nbsp;", join(', ', @{$status}), "\\l" if $status;
+        }
     }
     print "}\"];\n\n";
+
+    my $note = $spec->{description};
+    if ($note && $ENV{SPORE_NOTES}) {
+        $note =~ s/\n/\\n/g;
+        print "    \"__note__", $name, "\"\n";
+        print "        [label=\"", $note, "\" shape=note];\n\n";
+
+        print "    \"", $name, "\" -> \"__note__", $name, "\"\n";
+        print "        [arrowhead = none, arrowtail = none, style = dashed];\n\n";
+    }
+    my $doc = $spec->{meta}->{documentation};
+    if ($doc && $ENV{SPORE_NOTES}) {
+        $doc =~ s/\n/\\n/g;
+        print "    \"__doc__", $name, "\"\n";
+        print "        [label=\"", $doc, "\" shape=note];\n\n";
+
+        print "    \"", $name, "\" -> \"__doc__", $name, "\"\n";
+        print "        [arrowhead = none, arrowtail = none, style = dashed];\n\n";
+    }
 }
 print "}\n";