Skip to content

API · For developers

Tender data through an API

The data Tender Radar users see, in your ERP, CRM or warehouse: Prozorro, over a hundred commercial platforms and company portals, the EU, the UK and the UN. One format for every platform, refreshed every few minutes.

What the API gives you

Every tender comes in one format wherever it was published: number, title, buyer with its company id, CPV, expected value, deadlines in the buyer's time zone and in UTC, status and a link to the original. When the same tender is on several platforms you get one record listing every place it was published.

Sources

  • Prozorro — Ukraine's public procurement
  • Ukrainian commercial platforms and company procurement portals
  • European Union (TED)
  • National procurement systems of other countries, the UK among them
  • International organisations, the UN among them

Freshness

Each source is polled on its own schedule: the most frequent every few minutes, the rest from hourly to every few hours. The updated_at field says when a record last changed.

Tender fields

FieldDescription
idPermanent id of the record in Radar (UUID). Upsert your rows by it.
numberThe tender's number at the source, e.g. UA-2026-10-11-000337-a.
title · title_translated · description · languageTitle and description in the original language; a Ukrainian translation of a foreign tender's title when there is one.
status · status_sourceStatus on Radar's common scale, and the status as the source gives it.
procedureProcedure type: code and label.
buyerBuyer: name, EDRPOU or national id, region, locality.
cpvMain CPV code with its name, plus extra codes.
valueExpected value, currency and whether VAT is included.
published_at · submission_deadline · enquiry_end · auction_atDates and deadlines: the buyer's local time (local) and UTC (utc); time_zone is the buyer's time zone.
source · url · also_onSource, link to the original and the other platforms that publish the same tender.
lots · items · documentsLots, items and documents, when the source publishes them.
radar_url · first_seen_at · updated_atThe tender in Radar, when we first saw it and when the record last changed.

Authentication

Every request carries the organisation's key in the Authorization: Bearer rdr_live_… header. A key belongs to the company, not a person: give it to a service or an integration.

  1. 1Keys are created by the company's owner or admin in Tender Radar: Settings → «API».
  2. 2We show the full key once, right after it is created. Keep it in a secrets manager or an environment variable.
  3. 3We store only a hash of the key, so we cannot show it again. Lost a key? Revoke it and create a new one.
  4. 4A revoked key stops working at once. Give each integration its own key (up to 10 active).

Base URL

https://platform.aurum-apps.com/v1/data
Authorization: Bearer rdr_live_…

First request

Open roofing tenders in Ukraine. The key is read from the RADAR_API_KEY environment variable.

Endpoints

Every answer is JSON in UTF-8. Lists come as an object with a data field. List parameters can be repeated or comma-separated.

Tenders

GET/v1/data/tenders

Search and export tenders. The order is always (updated_at, id) ascending, so the cursor never skips a change.

ParameterDescription
qFree text, word forms included. An exact phrase goes in quotes, -word excludes.
cpvCPV codes or 2–8 digit prefixes (45 — construction, 4526 — roofing works).
countryISO 3166-1 alpha-2 country: UA, PL, GB…; EU — EU tenders from TED.
sourceSource codes from /v1/data/sources.
groupCompany group slugs from /v1/data/buyer-groups.
buyerBuyer: EDRPOU, national id or Radar buyer id.
statusopen (default) — a supplier can still bid and the deadline has not passed; any — every status; or specific statuses: planned, active, enquiry, tendering, auction, qualification, awarded, complete, cancelled, unsuccessful, closed_by_deadline, withdrawn_from_hub, notice, non_competitive.
value_min, value_maxExpected value from / to, in the tender's own currency.
deadline_from, deadline_toBid deadline from / to, ISO 8601 date-time.
updated_sinceISO 8601: only tenders created or changed at or after this moment.
cursorOpaque cursor from the previous answer's next_cursor.
limitPage size, 1–500, default 100.
langLanguage of CPV names, procedure labels and source names: uk (default), ru, en.
formatjson (default) or csv.
Sample response
{
  "data": [
    {
      "id": "0d6f4f7e-1c3b-4a51-9b7e-5b9b1f0c2a11",
      "number": "UA-2026-10-11-000337-a",
      "title": "Капітальний ремонт покрівлі",
      "status": "tendering",
      "source": { "code": "prozorro", "name": "Prozorro" },
      "value": { "amount": 1250000.0, "currency": "UAH", "vat_included": true },
      "submission_deadline": { "local": "2026-10-21T00:00:00+03:00", "utc": "2026-10-20T21:00:00Z" },
      "updated_at": "2026-10-11T19:31:02.123456Z",
      "…": "…"
    }
  ],
  "next_cursor": "eyJ1IjoiMjAyNi0xMC0xMVQxOTozMTowMi4xMjM0NTZaIiwiaSI6IjZmMWMifQ",
  "has_more": true,
  "as_of": "2026-10-11T19:40:00Z"
}

One tender

GET/v1/data/tenders/{id}

The full record by id. Unknown id: 404 tender_not_found.

No parameters.

Sample response
{
  "id": "0d6f4f7e-1c3b-4a51-9b7e-5b9b1f0c2a11",
  "number": "UA-2026-10-11-000337-a",
  "title": "Капітальний ремонт покрівлі",
  "title_translated": null,
  "description": "…",
  "language": "uk",
  "status": "tendering",
  "status_source": "active.tendering",
  "procedure": {
    "code": "aboveThreshold",
    "label": "Відкриті торги з особливостями"
  },
  "buyer": {
    "name": "Київська міська рада",
    "edrpou": "22883141",
    "scheme": "UA-EDR",
    "region": "Київ",
    "locality": "Київ"
  },
  "country": "UA",
  "region": "Київ",
  "source": {
    "code": "prozorro",
    "name": "Prozorro"
  },
  "url": "https://prozorro.gov.ua/tender/UA-2026-10-11-000337-a",
  "also_on": [
    {
      "source": "smarttender",
      "url": "https://smarttender.biz/…"
    }
  ],
  "cpv": {
    "main": {
      "code": "45261000",
      "name": "Покрівельні роботи"
    },
    "extra": [
      {
        "code": "45262000",
        "name": "…"
      }
    ]
  },
  "value": {
    "amount": 1250000,
    "currency": "UAH",
    "vat_included": true
  },
  "time_zone": "Europe/Kyiv",
  "published_at": {
    "local": "2026-10-11T10:15:00+03:00",
    "utc": "2026-10-11T07:15:00Z"
  },
  "submission_start": {
    "local": "2026-10-11T10:15:00+03:00",
    "utc": "2026-10-11T07:15:00Z"
  },
  "enquiry_end": null,
  "submission_deadline": {
    "local": "2026-10-21T00:00:00+03:00",
    "utc": "2026-10-20T21:00:00Z"
  },
  "auction_at": null,
  "lots": [],
  "items": [],
  "documents": [],
  "radar_url": "https://platform.aurum-apps.com/uk/app/tenders/0d6f4f7e-1c3b-4a51-9b7e-5b9b1f0c2a11",
  "first_seen_at": "2026-10-11T07:16:40Z",
  "updated_at": "2026-10-11T19:31:02.123456Z"
}

Sources

GET/v1/data/sources

Every source: code, country, segment, polling schedule, last successful run, status and number of open tenders. The codes go into the source parameter.

ParameterDescription
langLanguage of CPV names, procedure labels and source names: uk (default), ru, en.
Sample response
{
  "data": [
    {
      "code": "prozorro",
      "name": "Prozorro",
      "country": "UA",
      "segment": "ua_public",
      "kind": "api",
      "schedule_minutes": 5,
      "last_success_at": "2026-10-11T19:35:00Z",
      "status": "ok",
      "open_tenders": 18950
    }
  ]
}

Company groups

GET/v1/data/buyer-groups

Buyer groups (holdings) with their members and company ids. The slugs go into the group parameter.

ParameterDescription
langLanguage of CPV names, procedure labels and source names: uk (default), ru, en.
Sample response
{
  "data": [
    {
      "slug": "metinvest",
      "name": "Метінвест",
      "aliases": [
        "Metinvest"
      ],
      "members": [
        {
          "edrpou": "00191000",
          "name": "ПрАТ «ММК ім. Ілліча»"
        }
      ]
    }
  ]
}

CPV codes

GET/v1/data/cpv

Find CPV codes by code prefix or words, with names in three languages.

ParameterDescription
qCode prefix or words.
langLanguage of CPV names, procedure labels and source names: uk (default), ru, en.
limitHow many codes to return.
Sample response
{
  "data": [
    {
      "code": "45261000",
      "name": "Покрівельні роботи",
      "names": {
        "uk": "Покрівельні роботи",
        "en": "Roofing works",
        "ru": "Кровельные работы"
      }
    }
  ]
}

Usage

GET/v1/data/usage

Your key, its limits, how many requests and rows were used today and the state of your access.

No parameters.

Sample response
{
  "org": "ТОВ «Альфа»",
  "key": {
    "name": "ERP sync",
    "prefix": "rdr_live_ab12cd"
  },
  "limits": {
    "requests_per_minute": 120,
    "rows_per_day": 100000,
    "max_page": 500
  },
  "today": {
    "requests": 14,
    "rows": 1200,
    "rows_remaining": 98800
  },
  "subscription": {
    "status": "active",
    "plan": "api",
    "trial_until": null
  }
}

OpenAPI schema

GET/v1/data/openapi.json

OpenAPI 3 schema of the data API only; no key needed. Generate a client for your language from it.

No parameters.

Incremental sync

How to keep an up-to-date copy: load everything once, then fetch only the changes.

  1. 1First load: GET /v1/data/tenders?limit=500, then follow next_cursor while has_more is true. Save the last next_cursor.
  2. 2Every 10 minutes: GET /v1/data/tenders?cursor=…&status=any&limit=500, again while has_more. Upsert rows by id: a tender that changed comes again with its new state, e.g. closed_by_deadline. Save the new next_cursor.
  3. 3status=any so that closed and cancelled tenders also come through as changes. Rows you never had that are no longer open can be skipped.

No gaps and no duplicates: a change that is still being written is held back until it is committed, so the cursor never jumps over it. If a request breaks off, repeat it with the same cursor.

CSV export

Add format=csv and the same rows come as CSV: flat columns, comma-separated, a header row, UTF-8 with BOM (Excel opens it as is). The cursor comes in the X-Next-Cursor and X-Has-More headers, so the sync works the same way.

Limits

  • 120 requests per minute per key.
  • 100,000 tender rows per day per organisation (UTC day).
  • Up to 500 rows per page.
  • Both limits can be raised for your organisation — write to us.

Rate-limit headers

Every answer carries the current state of the limits:

HeaderDescription
X-RateLimit-LimitRequests per minute for this key.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetSeconds until the minute window resets.
X-RateLimit-Rows-LimitRows per day for the organisation.
X-RateLimit-Rows-RemainingRows left today.
Retry-AfterOnly on a 429: seconds to wait before retrying.

Errors

The error body is always the same: code for programs, message and detail for people. A validation error (422) has the standard body where detail lists the fields.

CodeWhat happened
401 missing_api_keyNo Authorization: Bearer header.
401 invalid_api_keyUnknown key.
401 api_key_revokedThe key was revoked.
402 api_plan_requiredThe organisation has no active API subscription.
400 invalid_cursorThe cursor is damaged or not from this API.
404 tender_not_foundNo tender with this id.
422 —A parameter is invalid.
429 rate_limitedToo many requests per minute; retry after Retry-After.
429 daily_rows_exceededThe daily row limit is used up; it resets at midnight UTC.
{
  "code": "invalid_api_key",
  "message": "Unknown API key",
  "detail": "Check the Authorization header"
}

The API comes with a subscription

Send a request: we agree the volume and the price, switch the subscription on for your organisation, and the owner or an admin creates a key right away.

Already have access? Keys are created in Settings → «API». Open settings

Get a key / Request access