API Documentation

Overview

This document provides guidelines and examples for API-accessible Service offering Analytic Tools.

You can use the GraphQL tool to manually issue GraphQL queries. If you navigate in a web browser to GraphQL, you should see an interface that lets you enter queries. Also, we prepared a list of example queries.

Try it

Authentication

Our API requests require authentication via an API key.

You can generate an API token on the Account page after registration. Note that you will need to specify the names of hosts that will use this API token.

Here is an example of the request with the authentication header:

POST /ua/prozorro/graphql HTTP/1.0
Authorization: Bearer 8d490d5334159f9811d3ce760971b16d1dcef663
Content-Length: 138
Content-Type: application/json
Host: ocdsanalytics.com

{
  "query": "{ Predictions{ Unit(page: {limit: 1} filters:{eq: {field:\"title\" value: \"fuel\"}}){ values{ entity{ id  } probability }}}}"
}



200 OK
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Tue, 23 Apr 2019 08:55:49 GMT
Server: gunicorn/19.9.0
Vary: Accept-Encoding

{
  "data": {
    "Predictions": {
      "Unit": {
        "values": [
          {
            "entity": {
              "id": "H87"
            },
            "probability": 0.50202125
          }
        ]
      }
    }
  }
}

If you are using our GraphQL interface, insert your API token into HTTP HEADERS section:

{
"AUTHORIZATION": "Bearer 8d490d5334159f9811d3ce760971b16d1dcef663"
}

Queries

The main aim of the OCDS Analytics is procurement analysis. In this documentation, we will start an explanation from simple requests and move to more complicated queries as it goes. The data output can be changed into whatever structure required using a variety of options.

To access data collection of Tenders you can use:

{
    Tenders {
    }
}

But in order to retrieve any data we need to ask for either some values or aggregation.

Let's indicate that we want to receive the values of the id field for each tender we have in our data collection as a basic request.

Example of a query will be as follows:

{
    Tenders {
        values {
        id
        }
    }
}

The result of such query will return the values of id for each tender we have in data collection and will look as follows:

{
  "data": {
    "Tenders": {
      "values": [
        {
          "id": "ef1a7c4f96ee49bfa711ab0391869674"
        },
        {
          "id": "ee2042b6a111499da701253beb8e4fd7"
        },
        ...
        }
      ]
    }
  }
}

Another example will be aggregation to count all tenders we have in our data collection.

Example of a query will be as follows:

{
  Tenders {
    aggregation {
      count
    }
  }
}

The result of such query will return aggregation which will count all tenders we have in data collection and will look as follows:

{
  "data": {
    "Tenders": {
      "aggregation": {
        "count": 3196773
      }
    }
  }
}

Pagination

If you have a lot of data, you may wish to add some sort of pagination to each page.

You can limit values when receiving data collection, without applying limit for aggregations:

  • limit: 4 means ‘return a maximum of 4 records’
  • offset: 3 means ‘skip the first 3 records’

Example of a query will be as follows:

{
  Tenders(page: { limit: 4, offset: 3 }) {
    values {
      id
    }
  }
}

The result of such query will return values of id for each tender we have in data collection but limited to 4 records per page and the first 3 records are skipped.

Notice! Pagination does not influence aggregations.

Please see the example below:

{
  Tenders(page: { limit: 4, offset: 3 }) {
    aggregation {
      count
    }
  }
}

Result:

{
  "data": {
    "Tenders": {
      "aggregation": {
        "count": 3309677
      }
    }
  }
}

As you can see pagination did not change the result of our aggregation.

Filtering

By applying a filter, you are able to limit your data collection in a view without altering the design of the underlying object.

There are several types of filters:

  • eq (equal to)
{eq: {field: "status" value: "active" }}
  • neq (not equal to)
{ neq: { field: "status", value: "invalid" } }
  • gte (greater or equal than)
{gte: {field: "probability", value: "0.5"}
  • gt (greater than)
  • lte (lesser or equal than)
  • lt (lesser than)

In order to apply only one filter use:

filters: {filter: {field: "" value: ""}

Example:

{
  Tenders(
    page: { limit: 4, offset: 3 }
    filters: { eq: { field: "status", value: "complete" } }
  ) {
    aggregation {
      count
    }
  }
}

Result:

{
  "data": {
    "Tenders": {
      "aggregation": {
        "count": 2694925
      }
    }
  }
}

For filtering by multiple fields use:

filters:[
{filter: {field: "" value: ""}
{filter: {field: "" value: ""}
...
]

Example:

{
  Tenders (
    filters: [
      {eq: {field: "status" value: "active" }}
      {eq: {field: "procurementMethod" value: "open"}}
    ]
  ){
  aggregation {
  count
  }
}
}

Result:

{
  "data": {
    "Tenders": {
      "aggregation": {
        "count": 51322
      }
    }
  }
}

There is an exception for filtering by such fields as procuring entity, tenderer, and winner, such fields are related fields for Identifiers data collection.

Syntax for filtering by related fields will be as follows:

filters: {filter: { 
           relatedField: {field: ""} } 
           value: ""
           } 
         }

In order to filter your data collection by a specific procuring entity, you need to use relatedField - procuringEntityIdentifier and input desired id as a value.

Example:

{
  Tenders(
    filters: {
      eq: {
        relatedField: { procuringEntityIdentifier: { field: "id" } }
        value: "37501627"
      }
    }
  ) {
    aggregation {
      count
    }
  }
}

In the result you will receive aggregation of count for all tenders of the procuring entity you've selected:

{
  "data": {
    "Tenders": {
      "aggregation": {
        "count": 481
      }
    }
  }
}

In order to filter by tenderer or winner simply change releatedField to the corresponding value and add the desired id.

For example, to find all tenders which particular tenderer participated in, that have status - active, and their procurementMethod is open use the query below:

{
  Tenders(
    filters: [
      {
        eq: {
          relatedField: { tenderersIdentifiers: { field: "id" } }
          value: "41412376"
        }
      }
      { eq: { field: "status", value: "active" } }
      { eq: { field: "procurementMethod", value: "open" } }
    ]
  ) {
    values {
      id
    }
  }
}

Result:

{
  "data": {
    "Tenders": {
      "values": [
        {
          "id": "e86df793696049918c658626e8b63985"
        },
        {
          "id": "b622a9b9d91e4cf98e58032015c6afaa"
        },
        {
          "id": "6c1f752617b74d869ac410dbd6aded74"
        }
      ]
    }
  }
}

Order

API allows sorting the display of results.

order requires two parameters:

  • sorting object (field or aggregation)
  • sorting direction: ASC or DESC

In order to apply order based on a field use:

order: { field: "", direction: "" }

In order to apply order based on an aggregation use:

 order: {
      aggregation: { aggregation { field: "" } } }
      direction: ""
    }

For cases when you base your query on Organizations and relation to Contracts, there is an opportunity to use the following objects:

  • contracts - when an organization is mentioned in a contract as either supplier or procuring entity
  • contractsAsSupplier - when an organization has a supplier role in a contract
  • contractsAsProcuringEntity - when an organization has a procuring entity role in a contract

For instance, to find the 3 largest suppliers use the following request:

{
  Organizations(
    page: { limit: 3 }
    order: {
      aggregation: { sum: { contractsAsSupplier: { field: "value.amount" } } }
      direction: "DESC"
    }
  ) {
    values {
      name
      contracts {
        aggregation {
          sum(params: { field: "value.amount" })
          count
        }
      }
    }
  }
}

Result:

{
  "data": {
    "Organizations": {
      "values": [
        {
          "id": "UA-EDR-31729022",
          "name": "СЕЛЯНСЬКЕ (ФЕРМЕРСЬКЕ) ГОСПОДАРСТВО \"КОМПРОМІС\"",
          "contracts": {
            "aggregation": {
              "sum": 380674739703.5,
              "count": 20
            }
          }
        },
        {
          "id": "UA-EDR-3013923104",
          "name": "ФОП Лозан Євгенія Олегівна ",
          "contracts": {
            "aggregation": {
              "sum": 380673772773,
              "count": 43
            }
          }
        },
        {
          "id": "UA-EDR-34795810",
          "name": "ТОВ \"Вікно-маркет\"",
          "contracts": {
            "aggregation": {
              "sum": 380505476495.8789,
              "count": 30
            }
          }
        }
      ]
    }
  }
}

Notice! order does not influence aggregation.

Examples

See more query examples here.

Predictions

This subsystem is designed to provide predictions based on machine learning modules. Predictions is a simple Django app, which is used as a plugin with the OCDS Analytics system.

Item Unit

Based on the inputs, we can get the most probable unit of measure. You are able to get Item Unit predictions with the following call:

    {
      Predictions {
        Unit(
          page: {limit: 4},
          filters:[
            {eq: {field: "tender.title", value: "Системи та пристрої нагляду та охорони (Двоканальний автомобільний відеореєстратор)"}},
            {eq: {field: "tender.description", value: "Системи та пристрої нагляду та охорони (Двоканальний автомобільний відеореєстратор)"}},
            {eq: {field: "item.description", value: "Двоканальний автомобільний відеореєстратор"}},
            {eq: {field: "item.classification.id", value: "35120000-1"}},
            {gte: {field: "probability", value: "0.02"}}
          ]){
          values{
            entity{
              id
              name
              symbol
            }
            probability
          }
        }
      }
    }

Results:

    {
      "data": {
        "Predictions": {
          "Unit": {
            "values": [
              {
                "entity": {
                  "id": "H87",
                  "name": "штуки",
                  "symbol": "шт."
                },
                "probability": 0.8850628733634949
              },
              {
                "entity": {
                  "id": "E50",
                  "name": "Одиниця",
                  "symbol": "од."
                },
                "probability": 0.05140087381005287
              },
              {
                "entity": {
                  "id": "KT",
                  "name": "комплект",
                  "symbol": "комп."
                },
                "probability": 0.04352602735161781
              }
            ]
          }
        }
      }
    }

Item Classification

Based on the inputs, we can get the most probable item classification. To get Item Classification predictions please use the following call:

    {
      Predictions {
        Classification(
          page: {limit: 3},
          filters:[
            {eq: {field: "tender.title", value: "Плитка керамічна"}},
            {eq: {field: "tender.description", value: "плитка керамічна"}},
            {eq: {field: "item.description", value: "Плитка керамічна Gress Атем Veneto, для підлоги, розмір – 400*400, колір – бежева, поверхня глазурована, матова"}},
            {eq: {field: "item.unit.id", value: "MTK"}},
            {gte: {field: "probability", value: "0.0002"}}
          ]){
          values{
            entity{
              id
              description
              scheme
            }
            probability
          }
        }
      }
    }

Results:

    {
      "data": {
        "Predictions": {
          "Classification": {
            "values": [
              {
                "entity": {
                  "id": "44110000-4",
                  "description": "Конструкційні матеріали",
                  "scheme": "ДК021"
                },
                "probability": 0.4496721625328064
              },
              {
                "entity": {
                  "id": "44111000-1",
                  "description": "Будівельні матеріали",
                  "scheme": "ДК021"
                },
                "probability": 0.15752540528774261
              },
              {
                "entity": {
                  "id": "44111700-8",
                  "description": "Кахель",
                  "scheme": "ДК021"
                },
                "probability": 0.09735838323831558
              }
            ]
          }
        }
      }
    }