= Translations API = Our intention is to provide APIs to Launchpad Translations starting with the import queue. From there, we'll follow an "oil slick" approach: from the translation queue we'll arrive naturally at exposing templates. Next is searching for templates on the one hand, and for translations of a template on the other. At that point it will also make sense to expose import queues for individual templates, and to support uploads. Download requests and individual messages come later, unless we come across high-priority work that requires them. == Applications == Some things we can do with the API: * [[https://blueprints.edge.launchpad.net/rosetta/+spec/import-queue-failed-error-display|Display import error output]]. * ''Add more here!'' Some cool things users could do with a Translations API: * Automate status tracking of their imports. * Client-side online translation. * Navigate the site in custom applications. == Designing an API == If you are working on a feature that involves adding or extending an API, keep that work in a separate branch. Sketch out what the API will look like and organize an API call with your team. Adding items to an API is very easy to do, and changing APIs is often painful. So worry more about exposing too much than about exposing too little! The API call will go over each element of the API: is it safe to expose? Is it something we'll end up regretting, or wanting to change? Is it maybe something that would be better exposed in another place altogether? You may be working on some complex feature that you don't want to hold up for a lengthy design discussion. When in doubt, leave out items that you don't have an immediate use for. If you can still think of a great use, file a bug or blueprint. === Properties === Start by identifying properties that can be exposed. The main risk is exposing information that is meant to be private: private team memberships, private bugs, and so on. If a property's name is unhelpful or misleading, change it: * Agree on a better name. * Expose it in the API under the better name. * File a bug about renaming the property inside Launchpad as well. * If you've got time, work on that bug so it doesn't haunt us forever! === Methods === Avoid adding operations that modify anything until you're confident enough with read-only ones. With read-only operations, the main risk besides exposing private information is overloading a server. When you expose a method, will you allow clients to do something that's much more costly than it is when triggered from a web page? You may want to expose only part of what a method does, and it may deserve a different name in that form. Or the existing name may simply be wrong. In that case, change it: * Agree on a better name. * Wrap it in a method with the better name, and expose that one. * File a bug about retiring the wrapped method, if appropriate. == Cheat sheet == Documentation in `lib/canonical/lazr/doc/webservice-declarations.txt`. Tests are in `lib/canonical/launchpad/pagetests/webservice`. Use `canonical.launchpad.lazr.interface.copy_field` to declare an API parameter with the same definition as an existing schema field. == Open issues == We still have some questions: * How do we define parameters or return values that can take different types? For instance, a "target" in the import queue may be an `IPerson`, `IProduct`, `IProductSeries` etc. * If an operation would be particularly costly, is there any way to rate-limit them in addition to anything that's already being done globally?