Unified Services goszakup.gov.kz - Version 2
One of our projects is the Public Procurement Portal of the Republic of Kazakhstan - goszakup.gov.kz.
A year ago, we launched a large project - Unified Services (OpenData).
For implementation, the RestAPI methodology was used.
Today I will talk about the new version of our services and the new interface for working with them.

We have developed and launched 6 Open Data services:
- Register of participants
- Register of unscrupulous suppliers
- Register of annual plans
- Announcements of state. procurement
- Lot Register
- Registry of contracts
Many companies in Kazakhstan are already connecting and receiving data on these services.
The launch of Open Data allowed us to reduce the database load by about 40% due to the fact that companies do not need to write various parsers to collect data on Public Procurement. It’s enough to go through a difficult quest :)
- write a request for an access token
- read the documentation for services on our portal goszakup.gov.kz/ru/developer/ows
- write your RestAPI client
Unified Services - A New Approach
RestAPI makes it possible to get data more conveniently and quickly than parsing a site, but the standard RestAPI does not give companies flexibility and to build a connection with objects you have to get all the data first and only then build the links between them.
In order to receive data on an announcement, it is necessary by RestAPI to request first the register of announcements, then the register of lots and finally the register of plans. This means that to receive one announcement, it is necessary to complete at least 3 requests, and if you need to receive data on 50 ads, you will need at least 101 requests to RestAPI, provided that each announcement will have 1 lot (1 to receive 50 ads, 50 to receive lots, 50 to receipt of plan points).
We have found a way to reduce this amount to one request!
We are launching the 2nd version of Unified Services -ows.goszakup.gov.kz/v2 .
In addition to expanding datasets, we are expanding the ability to work with our API.
Now the data can be obtained via RestAPI and the new interface - GraphQL.
ows.goszakup.gov.kz/v2/graphql

I will not describe what GraphQL is, for this you can read the article aliksend - What is this GraphQL?
I will tell you what advantages we got after starting GraphQL:
- Request flexibility;
- Getting related objects;
- Complete typing of requests and responses;
- New data search interface.
Request flexibility
With a simple RestAPI request, you get the data format that was laid in advance.
When you query GraphQL, you get the data in the format you need.
When requesting data, you yourself determine the format of the data that is needed, for example, the ID and
Contract number are needed
{
contract
{
id
contract_number_sys
}
}
In response, we get only this data:
{
"data": {
"contract": [
{
"id": 1,
"contract_number_sys": "номер_договора"
}
]
}
}
Well, such queries are the easiest to implement GraphQL. Companies are given the opportunity to choose what data they want to receive, while we do not need to make any adjustments as if it were when working with RestAPI. You get only the set of fields that is needed.

Retrieving Related Objects
We did not stop at repeating the functionality of RestAPI simply by making it possible to partially select data.
We have implemented the 2nd feature of GraphQL - object relationships.
If you receive data according to RestAPI, in order to receive data on the contract and on the company, the customer in the contract would first need to get data from the Register of Participants , and only then receive data from the Register of Contracts and build a connection between the objects themselves.
Now, when working with GraphQL, you don’t need to fully receive data from the Participant Register, just request data in the format you are interested in:
{
contract
{
id
contract_number_sys
customer
{
name_ru
}
}
}
Thus, with one request, we get both contract data and company data for the customer:
{
"data": {
"contract": [
{
"id": 1,
"contract_number_sys": "номер_договора",
"customer" : {
"name_ru": "Компания Мира"
}
}
]
}
}

And there are many such relationships that have been implemented, now companies to receive data will require significantly fewer requests to receive data. At the same time, one no longer needs to guess exactly how the objects are related to each other, to receive complete data sets in order to connect them with each other.
I tried to partially demonstrate the connection structure of which I managed to achieve.

Typing requests and responses
Many proponents of SOAP requests have always put the most important plus - data typing.
RestAPI, unlike SOAP, does not have a description of its structure and you do not know in advance what data type. But GraphQL changes everything.
Now you can request data from GraphQL throughout the data scheme and you will receive:
- Full description of the data structure;
- Description of which field has a data type (Int, String, Boolean);
- Description of nested objects and field structure of nested objects;
- Detailed description, for example, in Russian for each field;
- Receive a notification that some field has received the Deprecated flag with a description.
I use the program Insomnia REST Client - insomnia.rest
to work with GraphQL. When working with GraphQL, it receives the entire structure of objects and prompts when building a query.
I will give a few screenshots as an example.
1. Help in building queries since the program received the full structure of objects

2. Hint for the description of each field with its data type and description

3. Hint if any field received a flag - Deprecated

And this GraphQL feature allows you to have a complete picture of which fields and objects you work with.

New data retrieval interface
And I left the most interesting in the end.
Everything seems to be cool, it is possible to build your own data structure, there is a connection with other objects, all data is typed. But still, something is missing ...
There is not enough opportunity to search for this data.
From the beginning, a search format was implemented with the parameters in the request itself:
{
trd_buy(ref_buy_status_id: 1)
{
name_kz
name_ru
}
}
But here I ran into a number of problems:
- with a large number of search criteria, the query becomes simply unreadable;
- it is impossible to determine the array when searching for data to search for several variants of the same field.
To simplify the construction of queries, and to expand the search ability, I implemented nested objects for filtering data.
We define a variable in the request indicating the filtering object.
query($filter: TrdBuyFiltersInput){
trd_buy(filters: $filter)
{
name_kz
name_ru
}
}
We describe the data search parameters themselves:
{
"filter": {
"ref_buy_status_id": [1, 2]
}
}
And as a result, we get all the ads that have the statuses 1 and 2.
In the request, we indicate only the data structure, and all the search parameters go into the transmission of parameters where we can already transfer data arrays for filtering according to several criteria.

Moreover, in the GraphQL schema itself, we also all have a description of such a search object:

Unified Services - Version 2.0:
Services work:
- Register of participants
- Registry of announcements
- Registry of contracts
- Register of acts
- Lot Register
- Register of annual plans
- Register of unscrupulous suppliers
We launched a new functionality that greatly simplifies working with our API, has a flexible query structure and the ability to search for data according to specified criteria.
We have not lost in the speed of obtaining data, but only reduce due to this the number of requests necessary to obtain data.
We were able to warn in the data schema about disabled or renamed fields.
We plan to further develop the API and enable the morphological search of data on services as well.