<div dir="ltr">For a while, there's been some discussion about Kallithea's API design. It seems clear that nobody is really happy with the current JSON-RPC API, which is also in its current form quite limited.<br><br>There's been talk about adding a REST-like API, either in a separate API namespace or in the same namespace as the HTML user interface.<br><br>In the latter case, a request like GET /repo/pull-request/42 would return HTML by default, but JSON if the request came with an "Accept: application/json" HTTP header. While the idea has a conceptual purity to it, I'm not convinced by the feasibility of actually having both a REST-like API and the HTML UI share the same URL namespace. The two are quite different models, which we've learned the hard way in Kallithea with its use of _method overrides to fake DELETE and PUT requests from an HTML form (which can only generate GET and POST), a hack which has caused numerous headaches. Looking across the web, I know of no large website that tries to fit both REST API and browser access into the same URL namespace; they all maintain a separate API namespace.<br><br>Even then, deciding to add a new API under e.g. "/_api/" still leaves a lot of open questions, because the concept of a REST-like API is somewhat vague. For instance, it's quite straightforward to say "to request a PullRequest resource by ID, make a GET request to /_api/pull_requests/42", but a PullRequest consists of a number of "sub-resources", like the PR owner (a "User" object), reviewers, changesets, comments, etc.<br><br>One extreme is to only return IDs (or URLs, if you want to be more REST-like) for each of these sub-resources. If the caller wants e.g. changeset details, they'll then have to issue a long series of follow-up requests to fetch data about each of them, resulting in unacceptable performance. For this reason, most REST-like APIs return a wide selection of sub-resource data inline. This, on the other hand, often produces way too much data, again resulting in bad performance. See e.g. the GitHub API example for requesting a list of PRs for a repository: <a href="https://developer.github.com/v3/pulls/#response">https://developer.github.com/v3/pulls/#response</a> (and note that in that example, there's only ONE pull request in the resulting list).<br><br>At Unity, we've been experimenting with adding GraphQL support to Kallithea. For those who (like me just a few months ago) haven't heard of GraphQL, it's a standard for querying structured data (developed by Facebook), which tries to solve these problems.<br><br>Say that I want to get data for a specific PR. I just want the URL, title and reviewers. I don't need a list of revisions or PR comments; generating and transmitting those would be a waste of time. On the other hand, I _do_ want the review status for each reviewer, which is a somewhat expensive operation, and not something we'd want the API endpoint to calculate unless explicitly requested.<br><br>Using GraphQL, I can instead write a query like this, which succinctly describes the data that I'm after:<br><br>    {<br>        pull_request(id: 58) {<br>            html_url<br>            title<br>            reviewers {<br>                id<br>                full_name<br>                review_status<br>                avatar(size: 32)<br>            }<br>        }<br>    }<br><br>I can URL encode the above and put it into a HTTP URL like this:<br><br>    <a href="https://kallithea-scm.org/_admin/graphql?q=%7Bpull_request%28id%3A58%29%7Bhtml_url%20title%20reviewers%7Bid%20full_name%20review_status%20avatar%28size%3A32%29%7D%7D%7D">https://kallithea-scm.org/_admin/graphql?q=%7Bpull_request%28id%3A58%29%7Bhtml_url%20title%20reviewers%7Bid%20full_name%20review_status%20avatar%28size%3A32%29%7D%7D%7D</a><br><br>(As you can see, GraphQL only has one URL entrypoint, "/_admin/graphql" in this example.)<br><br>The response is plain JSON, for example:<br><br>    {<br>        "data": {<br>            "pull_request": {<br>                "html_url": "<a href="https://kallithea-scm.org/repos/kallithea/pull-request/58/_/bump_pytest_to_3.0">https://kallithea-scm.org/repos/kallithea/pull-request/58/_/bump_pytest_to_3.0</a>",<br>                "title": "test fixes noticed during Turbogears2 port (v3)",<br>                "reviewers": [<br>                    {<br>                        "id": 3,<br>                        "full_name": "Mads Kiilerich",<br>                        "review_status": "not_reviewed",<br>                        "avatar": "<a href="https://secure.gravatar.com/avatar/c13dec3bbff4e99b50c49c8cdbef6542?d=identicon&s=32">https://secure.gravatar.com/avatar/c13dec3bbff4e99b50c49c8cdbef6542?d=identicon&s=32</a>"<br>                    },<br>                    {<br>                        "id": 15,<br>                        "full_name": "Søren Løvborg",<br>                        "review_status": "approved",<br>                        "avatar": "<a href="https://secure.gravatar.com/avatar/170f30ed10c8ec5335aded8181949941?d=identicon&s=32">https://secure.gravatar.com/avatar/170f30ed10c8ec5335aded8181949941?d=identicon&s=32</a>"<br>                    }<br>                ]<br>            }<br>        }<br>    }<br><br>While this URL lacks the immediate readability of a more REST-like API, the original GraphQL query is quite clear, just a URL decode away, and much more flexible and expressive than anything based on plain key-value arguments in the URL query string.<br><br>I'd like to learn if there's general interest in this approach, and to see if people feel this would fit their API needs. (Obviously, having a GraphQL API doesn't preclude us from also having a REST-like API either, but it might make it redundant.)<br><br>My current proof-of-concept is not quite presentable yet, but I hope to have something to share soon-ish.<br><br>More info about GraphQL can be found here: <a href="http://graphql.org/">http://graphql.org/</a><br><br>Best,<br>Søren<br></div>