# Government Tenders Scraper - TED, SAM.gov, Procurement Data (`snow_leo_data/government-tenders-scraper`) Actor

19,795 notices in one week from the EU TED Tenders Electronic Daily API, where paged search stops at 15,000; 48 buyer countries in one measured window. UK and US SAM.gov notices with buyer email and phone. Government tenders API, SAM.gov contract opportunities search, public procurement database.

- **URL**: https://apify.com/snow\_leo\_data/government-tenders-scraper.md
- **Developed by:** [Snow Leo Data](https://apify.com/snow_leo_data) (community)
- **Categories:** Lead generation, Other, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.90 / 1,000 tenders

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## TED, SAM.gov & UK Government Tenders and Procurement Scraper

Public procurement notices from **four official feeds in one normalised
dataset**: TED (the European Union's Tenders Electronic Daily), UK Find a
Tender, UK Contracts Finder and US SAM.gov Contract Opportunities.

One run, one row shape, one set of filters. A buyer looking for construction
tenders above EUR 1 million closing this month writes that filter once, not
four times.

**48 buyer countries** were present in a single measured window: 47 of them in
one 7-day slice of TED (2026-09-04 to 2026-09-11, 19 795 notices), plus the
United States from SAM.gov. Reproduce it with
`python3 tools/measure_sources.py`.

***

### What this Actor collects

| Source | Covers | Notices measured |
|---|---|---|
| TED — Tenders Electronic Daily | EU, EEA, candidate countries; 47 buyer countries seen in one week | 19 795 in 7 days |
| UK Find a Tender | UK contracts above threshold | cursor feed, no published total |
| UK Contracts Finder | UK contracts below threshold | cursor feed, no published total |
| US SAM.gov Contract Opportunities | United States federal | 2 456 posted on 2026-09-10 alone |

Every one of the four is an open HTTPS endpoint that answers without an API
key, without a proxy and without a browser. That was checked with live
requests before this Actor was written, and it is why these four and not the
dozen other portals that demand a registration key.

#### Why does the notice count matter more than the country count?

Because a country list is easy to pad. Anyone can name twenty portals in a
description. The number that decides whether a monitor is useful is how many
notices actually arrive per day and whether you get all of them — and that is
where the two hard parts of this niche are.

***

### The two things that break naive tender scrapers

#### What happens when a TED search returns more than 15 000 notices?

TED's search API accepts `page` and `limit`, and refuses any combination where
`page × limit` exceeds **15 000**, with the error `SEARCH_WINDOW_TOO_WIDE`. It
does not warn you on the way in, and it does not tell you how many you lost.

Measured on 2026-09-11: a plain `publication-date>=today(-7)` query reports
**19 795** matching notices. A client that walks pages therefore reaches 15 000
and stops, silently dropping **4 795 notices — 24.2% of the week**.

This Actor uses TED's iteration cursor (`paginationMode: ITERATION`) instead of
page numbers, which has no such ceiling. The full 7-day window was walked end
to end in 80 requests of 250 and returned exactly 19 795 unique publication
numbers, with no repeats.

The live test suite proves both halves of that claim on every run:
`t_ted_window_cap_is_real` asks for page 61 and requires HTTP 400 mentioning
15000; `t_ted_cursor_goes_past_the_cap` collects more than 15 000 unique
notices through the cursor.

#### How do you read a 250 MB file without downloading 250 MB?

SAM.gov does not publish a date parameter at all. Its Contract Opportunities
extract is a single CSV of **249 740 888 bytes** and you are expected to take
the whole thing.

Measured over the first 25 000 rows on 2026-09-11: the file's `PostedDate`
column is **monotonically non-increasing** — newest notices first. So the
reader can stop as soon as the dates leave the requested window. For a 7-day
window that is roughly 11 000 rows instead of the full file.

The saving is not theoretical: at the download rate measured that day, the
full file took about 96 seconds of transfer before parsing began.

Because the whole trick rests on that ordering, the live suite re-checks it
every run (`t_sam_is_sorted_newest_first`). If SAM ever changes the order, the
test goes red rather than the data going quietly wrong.

***

### What comes back

**42 fields per notice.** The ones that take work rather than copying:

- `days_to_deadline` and `is_open` — computed at run time from the notice's
  closing date. `is_open` is `false` for awards and for passed deadlines, and
  `null` when no deadline was published, which is not the same thing.
- `cpv_division` and `cpv_division_label` — the CPV sector spelled out in
  English ("45 — Construction work"). No source publishes the label, only the
  digits.
- `value_eur_estimate` — the published amount converted at a fixed rate table
  dated 2026-09-11, so that one sort works across 19 currencies. It is named
  an estimate because it is one; `value_amount` and `value_currency` always
  carry exactly what the source said.
- `notice_type_label` — `cn-standard` becomes "Contract notice".
- `buyer_country` — ISO-3166 alpha-3 for every source. TED sends `DEU`, the UK
  feeds send `GB`, SAM.gov sends `USA`; you should not have to care.
- `change_type` — `NEW` or `UPDATED` in monitor mode.

Plus the buyer's `buyer_email`, `buyer_phone`, `buyer_contact_point`,
`buyer_website`, the `award_winner_name` on award notices, `submission_url`,
and the notice's own public `notice_url`.

#### How full are those fields really?

Measured on 150 live rows from each source on 2026-09-11 with
`python3 tools/fill_rates.py 150`:

| Field | TED | Find a Tender | Contracts Finder | SAM.gov |
|---|---|---|---|---|
| `title`, `buyer_name`, `buyer_country`, `notice_url` | 100% | 100% | 100% | 100% |
| `buyer_email` | 100% | 100% | 100% | 100% |
| `buyer_phone` | 100% | 21% | 50% | 44% |
| `cpv_codes` | 100% | 97% | 100% | 0% |
| `deadline_date` | 49% | 26% | 100% | 71% |
| `value_amount` | 68% | 35% | 82% | 27% |
| `award_winner_name` | 36% | 58% | 93% | 27% |
| `naics_code` | 0% | 0% | 0% | 99% |

An empty cell here is the source not publishing the field, not this Actor
failing to read it — with two exceptions that were this Actor failing to read
it, and were fixed:

- **CPV on Find a Tender went from 13% to 97%.** The obvious place to read a
  CPV code is `tender.classification`. On 30 live releases that field carried a
  code in 3 of them; `tender.items[].additionalClassifications` carried one in
  15, and awards carry more. Reading only the obvious place leaves most of the
  feed with no sector at all, which then silently breaks every sector filter.
- **The public notice URL on Contracts Finder went from 7% to 100%.** Only 7%
  of releases publish an HTML document link. The rest are reachable by
  stripping the trailing `-<serial>` from the release id, which is what the
  service's own notice pages do.

***

### Filters, and why they run before you are charged

Every filter in the input form is applied **before** a row is written to the
dataset. On a pay-per-result Actor that is the difference between paying for
what you asked for and paying for what the source happened to publish.

Where the source can do the filtering, it does. Keyword, country, sector and
notice type are pushed into TED's own query language, so non-matching notices
are never even downloaded. The UK and US feeds have no text or sector
parameters, so the same filters run locally for them — still before the push.

#### Why is the keyword filter not applied twice to TED rows?

Because TED's full-text index searches the whole notice document, and this
Actor only downloads the fields it asked for. Re-running the keyword match
locally would throw away rows TED had already matched on text we never
received. Each source declares which filters it has already honoured
(`filters.SERVER_SIDE`), and those are not repeated. There is a test for it,
and a deliberate-breakage proof that the test catches its removal.

#### Can I exclude words, or watch one particular buyer?

Yes. **Exclude keywords** drops any notice containing one of your words in its
title, description or buyer name. **Buyer name contains** keeps only notices
from authorities whose name matches — one ministry, one council, one agency.
Both run before billing, like every other filter. Closing dates can be bounded
from both sides with **Deadline from** and **Deadline to**, or loosely with
**Deadline within N days**.

#### What stops one source from eating the whole limit?

With several sources selected, `maxItems` is split evenly between them unless
you override it with `maxItemsPerSource`. Without that split, a request for
200 notices from four sources returns 200 notices from whichever source runs
first, and the run looks like a single-country scraper.

#### What does "only notices still open" actually drop?

Awards, and anything whose deadline has passed. It deliberately **keeps**
notices with no published deadline: on these feeds a missing deadline is
normal for prior information notices, and dropping them would hide a whole
class of notice from everyone using the filter. Measured above: TED publishes
a deadline on 49% of notices and Find a Tender on 26%.

***

### Monitor mode

Turn on **Monitor mode — only what changed** and schedule the Actor daily.

It remembers which notices it has already delivered in a **named** key-value
store, which survives between runs (the default store does not — it is wiped
at the start of every run, and an incremental mode built on it quietly
degrades into a full re-scrape that charges you again every morning).

Each delivered row is labelled `NEW` or `UPDATED`. A notice counts as
`UPDATED` when its title, buyer, deadline, value, notice type or the first
2 000 characters of its description changed — not when the source touched some
invisible internal field, which would make everything "updated" every day.

Unchanged notices are not returned at all unless you ask for them. You already
paid for those rows once.

Memory holds 70 000 keys and discards the oldest first when it overflows.

#### What happens if a run is cut off half way through?

Rows are written to the dataset first and marked as delivered second, never
the other way round. If the container is moved or the run times out mid-push,
the notices that did not make it out are still unknown to the memory and
arrive on the next run. The opposite order loses them permanently, which is
the kind of bug you only find by testing for it — so there is a lifecycle test
that cuts a multi-batch push in half and asserts that memory never runs ahead
of delivery.

***

### Output shapes for agents

- **Compact output** returns 15 fields instead of 42 — the ones a language
  model or a spreadsheet actually reads.
- **Drop empty fields** omits keys whose value is null or empty rather than
  sending them. Given the fill-rate table above, that is real noise removed,
  not cosmetics.
- **Include the description text** can be turned off entirely when you only
  need metadata; descriptions are by far the largest part of a row.
- **Include the raw source record** does the opposite: it adds a `raw` field
  holding the untouched payload the source sent, next to the normalised
  columns, for when you need something this Actor does not map yet.

***

### Honest limitations

Named here rather than left for you to discover:

- **SAM.gov has no CPV codes and no works/supplies/services split.** The US
  classifies with NAICS. `naics_code` is filled on 99% of SAM rows, but the
  sector filter in this form is CPV-based and therefore does not apply to
  SAM.gov. Filter US rows by keyword or by NAICS downstream.
- **The notice type filter applies to TED only.** The UK feeds use OCDS tags
  and SAM.gov uses its own vocabulary; both are reported in `notice_type` and
  `notice_stage`, but the picker's eForms codes are TED's.
- **`value_eur_estimate` uses a fixed rate table, not live rates.** The table
  is dated in the code (`normalize.EUR_RATES_DATE`). For a contract closing
  next month that is entirely adequate; for currency arbitrage it is not.
- **TED publishes a deadline on about half its notices** and Find a Tender on
  about a quarter. That is the source, not the reader. Notices with no
  deadline keep `days_to_deadline` and `is_open` as `null` rather than
  guessing.
- **Descriptions come from one lot.** A TED notice split into many lots has
  many descriptions; this Actor carries the first in your preferred language
  and the notice URL for the rest.
- **No award values for UK Contracts Finder awards without a published
  amount** — 18% of the measured sample had none.
- **Tender documents are not downloaded.** `documents_url` and
  `submission_url` point at them; the files themselves stay where they are.
  Some competitors fetch attachments, at the cost of a much slower and much
  more expensive run.
- **There is no sub-country region filter.** Buyer city and postcode are
  published; NUTS and state-level filtering is not exposed in this form.
- **You cannot feed it individual notice URLs.** This Actor searches the four
  APIs; it is not a single-page fetcher.
- **There are no proxy or concurrency knobs**, because all four sources answer
  plain requests without one. If a source ever starts blocking, that is a
  change to this Actor, not a setting for you to tune.
- **No built-in webhook fields.** Apify's own webhooks fire on run finish and
  do the same job without a second copy of the feature.
- **This Actor does not bid for you.** It finds and normalises notices.

***

### FAQ

#### Do I need an API key for any of this?

No. All four sources answer anonymous HTTPS requests. There is nothing to
register for and nothing to renew.

#### How fresh is the data?

TED publishes on working days; the window measured on 2026-09-11 held 19 795
notices from the previous seven days. SAM.gov's extract had 2 456 notices
posted on 2026-09-10. The two UK feeds are cursor-based and return whatever
has been published up to the moment of the request.

#### Can I search in a language other than English?

Yes. TED publishes titles and descriptions in up to 24 languages, and
**Preferred language** picks which one lands in the `title` and `description`
columns. If a notice has no text in your language the next available one is
used rather than leaving the row blank. `languages_available` tells you how
many translations existed.

#### What is CPV and why should I filter by it?

CPV is the European Common Procurement Vocabulary: an eight-digit code whose
first two digits name the sector. Picking division 45 in this form matches
**every** code inside it — `45213316`, `45000000` and the rest — rather than
only notices tagged with the bare division code. Testing equality instead of
the prefix is a common mistake and returns a tiny fraction of the real matches.

#### Can I write my own TED query?

Yes. **Advanced — TED expert query** takes TED's expert search syntax verbatim
and replaces every generated clause, for example:

```
publication-date>=today(-3) AND buyer-country IN (DEU AUT) AND classification-cpv IN (72000000)
```

The other sources keep using the form's filters.

#### How do I get only the awards, to see who won what?

Set **Stage** to "Awards only". `award_winner_name`, `award_winner_country`,
`value_amount` and `value_currency` carry the result. On the measured sample
that is 36% of TED rows and 93% of Contracts Finder rows.

#### Why are there two UK sources?

They cover different money. Find a Tender carries contracts above the public
procurement thresholds; Contracts Finder carries the below-threshold ones plus
a large stream of awards. Most UK suppliers want both, and they are separate
services with separate APIs.

#### What does the run report contain?

The `REPORT` record in the key-value store holds the date window, per-source
delivered and scanned counts, how many rows each individual filter removed,
the `NEW`/`UPDATED`/`UNCHANGED` tally, the list of buyer countries seen, and
any source that failed. A source that fails does not kill the run; it is
reported and the others continue.

#### How do I check the claims in this README?

Every number above comes from a tool shipped with this Actor, in `tools/`:

- `python3 tools/measure_sources.py` — notice counts, country count, the
  15 000 ceiling and the SAM ordering, all against the live APIs.
- `python3 tools/fill_rates.py 150` — the fill-rate table.
- `python3 tests/run_all.py --live` — logic, deliberate-breakage proof,
  lifecycle and live-source suites.
- `python3 tools/verify_readme.py` — checks that the numbers written here
  still match the code and the schemas.

#### What else is this called?

Names buyers use: government tenders scraper, public procurement data, TED contract notices, SAM.gov opportunities, procurement deadline tracker. Every row carries the days left to the submission deadline, so a deadline tracker is the same feed read by date.

Other names for the same feed: public sector bidding data, TED Europa tenders, solicitation notices, contracting authority or buyer lookup, open tender procedure type, CPV code search. They map to the fields `value_amount`, `source_label`, `notice_type`, `buyer_name`, `procedure_type` and `cpv_codes`.

# Actor input Schema

## `sources` (type: `array`):

Which public procurement feeds to read. Every one of them is an open, key-free API: TED covers the EU, the EEA and the candidate countries (47 buyer countries were measured in a single 7-day window), the two UK services cover above- and below-threshold British contracts, and SAM.gov covers United States federal opportunities.

## `keyword` (type: `string`):

Free-text search. On TED this is pushed into the API's own full-text index, so notices that do not match are never downloaded and never charged. On the UK and US feeds, which have no text parameter, the words are matched against title, description and buyer name before anything is written to the dataset.

## `datePreset` (type: `string`):

How far back to look. Pick Custom to type exact dates below.

## `excludeKeywords` (type: `array`):

Drop any notice containing one of these words in its title, description or buyer name. Applied before you are charged.

## `publicationDateFrom` (type: `string`):

Used only when the range above is set to Custom. Format YYYY-MM-DD.

## `publicationDateTo` (type: `string`):

Used only when the range above is set to Custom. Format YYYY-MM-DD.

## `countries` (type: `array`):

Leave empty for every country in the selected sources. The counts come from one live 7-day TED window, so they show where the volume actually is, not where it is assumed to be.

## `buyerNameContains` (type: `string`):

Keep only notices whose contracting authority name contains this text. Useful for watching one ministry, council or agency.

## `cpvCodes` (type: `array`):

CPV is the European sector vocabulary. Picking a division matches every code inside it, so 45 returns all construction work, not only notices tagged with the bare division code. SAM.gov classifies with NAICS instead and is not filtered by this.

## `noticeTypes` (type: `array`):

Restrict to particular eForms notice types. Applies to TED only.

## `contractNature` (type: `string`):

Works, supplies or services. Published by TED and by both UK feeds; SAM.gov does not publish it.

## `stage` (type: `string`):

An opportunity is something you can still bid for; an award names who won. Both are useful, and they are usually mixed together in one feed.

## `openOnly` (type: `boolean`):

Drop awards and anything whose deadline has passed. Notices with no published deadline are kept: on these feeds a missing deadline is normal for prior information notices, and dropping them would hide a whole class.

## `deadlineWithinDays` (type: `integer`):

Keep only notices closing within this many days. Leave empty for no limit.

## `deadlineFrom` (type: `string`):

Keep only notices closing on or after this date, YYYY-MM-DD. Notices with no published deadline are kept.

## `deadlineTo` (type: `string`):

Keep only notices closing on or before this date, YYYY-MM-DD.

## `minValueEur` (type: `integer`):

Compared against value\_eur\_estimate, which converts the published amount at a fixed rate table dated 2026-09-11. Notices with no published value are kept, because most contract notices publish a value only at award time.

## `maxValueEur` (type: `integer`):

Upper bound on value\_eur\_estimate. Leave empty for no ceiling.

## `sortBy` (type: `string`):

Order of the rows within each source. Sorting happens after filtering, so it never costs you extra rows.

## `outputLanguage` (type: `string`):

TED publishes titles and descriptions in up to 24 languages. This picks which one to put in the title and description columns; if the notice has no text in it, the next available language is used rather than leaving the row blank.

## `maxItems` (type: `integer`):

Total across all selected sources. 0 means no limit. With several sources selected the limit is shared between them, so one large feed cannot eat the whole run.

## `maxItemsPerSource` (type: `integer`):

Overrides the automatic even split. 0 leaves the split alone.

## `includeDescription` (type: `boolean`):

Turn off for a much smaller dataset when you only need the metadata.

## `compactOutput` (type: `boolean`):

Return only the fields an agent or a spreadsheet actually reads. Useful when the dataset is fed to a language model and every field costs tokens.

## `dropEmptyFields` (type: `boolean`):

Omit keys whose value is null or empty instead of sending them. Not all sources publish all fields, so this removes real noise.

## `includeRawSource` (type: `boolean`):

Add a raw field holding the untouched payload from the source, next to the normalised columns. Useful when you need a field this Actor does not map yet.

## `incrementalMode` (type: `boolean`):

Remembers which notices were already delivered, in a named key-value store that survives between runs, and returns only new and edited ones. Each row is labelled NEW or UPDATED. This is what makes a daily schedule cheap: you pay for the dozens that changed, not for the thousands that did not.

## `emitUnchanged` (type: `boolean`):

Only meaningful with monitor mode on. Off by default, because you already paid for those rows once.

## `tedExpertQuery` (type: `string`):

Replaces every generated TED clause with your own, in TED's expert search syntax, for example: publication-date>=today(-3) AND buyer-country IN (DEU) AND classification-cpv IN (72000000). When this is set the filters above still apply to the other sources.

## `samMaxRowsScanned` (type: `integer`):

SAM.gov publishes one 250 MB CSV with no date parameter, but it is sorted newest first, so this Actor stops reading as soon as the dates leave your window. This is the hard stop in case the ordering ever changes.

## `tedPageSize` (type: `integer`):

Notices per TED request. 250 is the maximum the API accepts and the default; lower it only if you are hitting timeouts.

## Actor input object example

```json
{
  "sources": [
    "ted"
  ],
  "keyword": "software",
  "datePreset": "last_7_days",
  "excludeKeywords": [],
  "countries": [],
  "buyerNameContains": "Ministry of Defence",
  "cpvCodes": [],
  "noticeTypes": [],
  "contractNature": "",
  "stage": "any",
  "openOnly": false,
  "sortBy": "publication_date_desc",
  "outputLanguage": "eng",
  "maxItems": 200,
  "maxItemsPerSource": 0,
  "includeDescription": true,
  "compactOutput": false,
  "dropEmptyFields": false,
  "includeRawSource": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "samMaxRowsScanned": 120000,
  "tedPageSize": 250
}
```

# Actor output Schema

## `results` (type: `string`):

All collected rows

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keyword": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("snow_leo_data/government-tenders-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "keyword": "" }

# Run the Actor and wait for it to finish
run = client.actor("snow_leo_data/government-tenders-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keyword": ""
}' |
apify call snow_leo_data/government-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,snow_leo_data/government-tenders-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HAoWSVkY3xJUJ6J3S/builds/mQ528q87vYGdySYqS/openapi.json
