Admin as a unit test for HTTP API
Greetings, colleagues. Many Internet services provide HTTP APIs for developers. There are many articles on how to do it right, no less stories about how it turned out wrong, and a powerful bunch of criticism of what happened to others. It’s hard to make a good API - it constantly tries to drop out of Miller’s wallet , acquire cyclic dependencies among entities and put the poor developer in the Procrustean bed of usage scenarios “as developers see them”. I’ll add my own five kopecks - under the cut, a funny, but working way, which we use to tame our rather big HTTP APIThe best frameworks and APIs are extracted from live projects
On the Internet, I often come across the claim that successful frameworks and APIs were extracted by authors from working, commercial projects. How did the Django framework come about? The authors have made many news sites. At some point, they realized that part of the code was crawling from project to project. They took this code to a separate library - we got a web framework. How did the Amazon API come about? Did interfaces of interaction between internal services. After some time, the API stabilized, began to change less and less, and finally it was made available to external clients.Extracting something from a live project, we don’t need to try to “write on paper” the use cases, which usually doesn’t work out very well. Despite the brainstorming crutches, diagrams, and wiki, people are not very well equipped to hold new complex systems in their heads, and many attempts to come up with a complex API “on paper” end up completely redone a few months after the release.
But what if the project is initially a platform, and there are no “commercial projects” from which to extract parts of it yet in nature? Many managers in such cases suggest that development teams make “mock-ups” of potential solutions and develop APIs for such mock-ups. Alas, the layout “invented from the head” is often very different from what real users will create. Not because they were badly invented, but because of the limitations of our brain on the amount of information held in focus.Admin as a reference application
Many years ago, when we were just starting to create voximplant, we had a large pile of hotel clients and the understanding that the first time a good API could not be done. But really wanted to. And during the next brainstorming a strange idea was born: to make the admin panel for developers not on the backend, as they did for most projects then, but on the frontend. And so that the admin panel for all its functions uses the same HTTP API that we give to our customers.
A huge plus of this approach is that the design of the API evolves with the admin panel. At the beginning, this is a blank sheet with the “add user” button. For the button to work, we make an AJAX call and the / AddUser method on the server side. Add user ID input field - add user_name paired argumentfor the API method - and so on, until the basic functionality is created. Of course, this approach is not suitable for everyone. Software development is a very large area. There is development according to customer specifications, when the entire API is completely designed by a specially trained team of architects. There are situations when the API reflects only a small part of the platform’s functionality, accessible to external developers “sandbox”. There is a development under the contract, when everything needs to be thought out and calculated in advance in order to predict the timing and budget.
Nevertheless, this method helped us very well. And, as far as I see on the Internet, more and more services with a developed API adhere to the principle of “eat your own dog food”, using these APIs to develop your own admin panel and services. While the startup does not have comprehensive documentation and training materials for all occasions, the client’s question “how to do this” can always be answered - “do the actions in the admin panel and look in chrome dev tools what requests and with what arguments it performs”. This approach works - and it works well.
Further Evolution: How to Use AttachPhoneNumber
Admin is a good thing, but for many services it allows you to do only the most popular operations, while “complex” cases remain under the hood or are accessible via API. As an example, I will show our API function / AttachPhoneNumber which allows you to rent a phone number so that in the future using javascript scripts to manage calls coming to this number. In the admin panel when buying a room, you can filter the available numbers by country / type / city, select the number you like or indicate the number of rooms for rent, and then click on the “buy” button:

If you look at our documentation for the corresponding API method, you can easily find a correspondence between what we see in the interface and what we can pass to the API function:
- Different authorization options. They are the same for most API methods and are described at the beginning of the documentation.
- The number of numbers that we want to rent for one request is transferred to phone_count : from one to ... how many are.
- In country_code when transmitted code of the country, for Russia it is " RU ", the full list can be viewed ... yes, in the same admin:

- The category of the number is transferred to phone_category_name : direct city, mobile, 8-800- and so on. A list of categories can also be viewed in the admin panel or retrieved for a specified country using the GetPhoneNumberCategories API function - for example, for city numbers in Russia it will be “ GEOGRAPHIC ”.
- The “region identifier” is passed to phone_region_id . This is some internal identifier used by telecoms from different countries providing numbers. You can traditionally peek at the list , but it’s better to get it using the special GetPhoneNumberRegions API , which returns a list of available regions for the specified country and category of number.
- The telephone addressing of some countries in the region is not enough, and for such countries, when purchasing multiple numbers, the state identifier is passed in the country_state parameter . A list of states can be obtained using GetPhoneNumberCountryStates - for those countries where they are.
As you can see, all these values are reflections of the corresponding fields of the form and were added as functionality was added: first there was the opportunity to buy by number, then we added a choice of the number of rooms, which pulled the need to indicate which numbers are of interest to the client, then there were partners and the opportunity to buy by number is outdated - and so on.
How to get a number in Japan and answer a call
A practical example of how the creators of applications on our platform can use the API, guided by the admin panel as a reference implementation. Suppose we want to rent a number in Tokyo and do javascript when calling this number. For demonstration purposes only, of course. First we need to find out the number of rooms available - did Tokyo suddenly end? For authorization, we use the account identifier and the key from the voximplant admin settings, and to request the number of numbers, use the specially trained GetPhoneNumbers method :
curl "https://api.voximplant.com/platform_api/GetNewPhoneNumbers/?account_id=1&api_key=2&country_code=JP&phone_category_name=GEOGRAPHIC&phone_region_id=8384"
In response, we get a json
curl "https://api.voximplant.com/platform_api/AttachPhoneNumber/?account_id=1&api_key=2&country_code=JP&phone_category_name=GEOGRAPHIC&phone_region_id=8384&phone_count=1"
After a couple of seconds of thought, we get JSON with the parameters of the rented number, it looks like this:
{
"result":1,
"phone_numbers":[
{
"phone_number":"81345793488",
"verification_status":"VERIFIED",
"phone_id":9033
}
]
}
In the answer we can see the number itself (I got 81345793488). In this issue, “+81” is the code of Japan, “3” is the code of Tokyo (note that it does not coincide with the region identifier for Tokyo, which we set as “8384”, because the region identifier is the internal identifier of the telecom) and “ 45793488 ”- actually the number itself. To take a call on him and do something useful, you need to connect it with one of the voximplant applications - which can also be created through the API. An example of such a command that will connect the rented number with the application “foo” (yes, I have such an application. It says “hi” and hangs up):
curl "https://api.voximplant.com/platform_api/BindPhoneNumberToApplication/?account_id=1api_key=2&phone_number=81345793488&application_name=foo"
We hope that this small case will add a little trick to your piggy bank of web development techniques - perhaps someday in the future this approach will save you from many sleepless nights spent on the design of the “ideal api”. In the comments, I’m traditionally ready to answer unconstructive criticism, answer tricky questions and just talk about the design and development of the API.