# Biddingo Public Tenders Scraper (`automation-lab/biddingo-public-tenders-scraper`) Actor

🇨🇦 Find public Biddingo tenders with buyers, locations, deadlines, descriptions, addenda, Q\&A, submission, result, and award indicators.

- **URL**: https://apify.com/automation-lab/biddingo-public-tenders-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Biddingo Public Tenders Scraper

Find Canadian procurement opportunities before their deadlines.

Biddingo Public Tenders Scraper exports current public bid listings from Biddingo into clean JSON, CSV, Excel, XML, RSS, or Parquet through Apify.

Search by keyword, buyer, region, province, city, and date.

Optionally enrich every opportunity with its anonymous public bid detail, categories, contact emails, description, and source-native workflow flags.

No Biddingo login is required for the data covered by this Actor.

### What does Biddingo Public Tenders Scraper do?

The Actor queries Biddingo's anonymous Canadian opportunity search and public bid details.

Each dataset row represents one tender, quotation, RFP, RFQ, or related procurement opportunity.

It collects:

- 🔎 solicitation number and Biddingo IDs
- 🏢 public buyer name
- 📍 region, province, city, and postal code
- 📅 posted date, closing date, time zone, and days left
- 🧰 bid and procurement type
- 📄 description and public categories
- ✉️ contact emails and external opportunity links
- ➕ addendum and special-notice indicators
- ❓ Q&A and site-meeting indicators
- 🏆 result and award indicators
- 📤 online and paper submission indicators
- 🔒 research/masking indicators

The Actor never purchases documents or attempts to reveal subscription-only fields.

### Who is it for?

#### Canadian contractors

Monitor relevant construction, roofing, maintenance, equipment, and service opportunities without manually checking Biddingo every morning.

#### Bid consultants

Create client-specific feeds by keyword, buyer, or geography and triage opportunities by deadline.

#### Suppliers and distributors

Identify public-sector demand for products and services across Canadian provinces.

#### Procurement intelligence teams

Feed structured opportunities into BI tools, CRMs, warehouses, and alerting systems.

#### Researchers

Analyze publicly visible procurement activity while preserving Biddingo's explicit masking markers.

### Why use this Biddingo scraper?

- ⚡ **HTTP-first:** it uses lightweight public JSON routes rather than an expensive browser.
- 🔁 **Repeatable:** save an input as an Apify Task and schedule it daily.
- 📊 **Structured:** export normalized fields instead of copying rows from a web page.
- 🎯 **Filtered:** narrow records by buyer, province, city, dates, or keywords.
- 🔗 **Traceable:** every item includes its public Biddingo detail and source-search URL.
- 🛡️ **Transparent:** researched or masked rows are labeled instead of falsely enriched.
- 🧩 **Integratable:** connect datasets to webhooks, Make, Zapier, Google Sheets, or your own API.

### What Biddingo tender data can I extract?

| Field | Meaning |
|---|---|
| `biddingoTenderId` | Stable Biddingo opportunity ID |
| `procurementId` | Biddingo procurement identifier when present |
| `solicitationNumber` | Public RFQ, RFP, tender, or quote number |
| `title` | Opportunity title |
| `buyerName` | Public buyer or issuing organization |
| `region` | Biddingo geographic region |
| `province`, `city`, `postalCode` | Public location fields |
| `postedDate` | Normalized publication date |
| `closingDate` | Normalized deadline date |
| `closingDateTime` | Source deadline text with time |
| `closingTimeZone` | Source time-zone abbreviation |
| `status`, `daysLeft` | Current bid status and days remaining |
| `bidType`, `procurementType` | Source procurement classifications |
| `categories` | Public Biddingo category names |
| `description` | Plain-text public bid description |
| `contactEmails` | Emails found in the public detail |
| `externalUrls` | Public external opportunity or submission links |
| `hasAddendum`, `hasQna` | Addendum and Q&A indicators |
| `hasSiteMeeting`, `hasNda` | Site meeting and NDA indicators |
| `hasResult`, `hasAward` | Result and award indicators |
| `hasOnlineSubmission` | Whether source data indicates online submission |
| `documentCount`, `addendumCount` | Public source counts |
| `isResearchBid`, `isMasked` | Restricted/researched record markers |
| `detailUrl`, `sourceSearchUrl` | Traceable public source URLs |
| `scrapedAt` | UTC collection timestamp |

### How to scrape Biddingo public tenders

1. Open the Actor input page.
2. Enter a useful phrase such as `roofing`, `snow removal`, or `software`.
3. Keep **Open for bidding** selected for an active opportunity feed.
4. Optionally set a province, city, buyer, or deadline filter.
5. Choose a small `maxItems` value for your first run.
6. Leave detail enrichment enabled when you need descriptions and categories.
7. Click **Start**.
8. Review the Dataset and export it in your preferred format.
9. Save the configuration as a Task if you want a scheduled monitor.

### Input parameters

#### Search

- `keywords` — optional full-text Biddingo search phrase.
- `searchUrls` — one or more Biddingo `/search` URLs; these override the generated search.
- `status` — collect open opportunities or all statuses returned by Biddingo.

#### Buyer and location

- `buyer` — case-insensitive buyer-name filter.
- `region` — Biddingo region filter, such as `Eastern Canada`.
- `province` — province filter, such as `Ontario`.
- `city` — city filter.

#### Dates and pagination

- `postedAfter` — inclusive earliest posted date in `YYYY-MM-DD`.
- `closingBefore` — inclusive latest closing date in `YYYY-MM-DD`.
- `offset` — initial Biddingo API offset.
- `maxItems` — maximum unique records across all searches.

#### Enrichment

- `includeDetails` — request public detail JSON for richer fields.
- `requestDelayMs` — delay between requests, from 0 to 5,000 ms.

### Example input

```json
{
  "keywords": "roofing",
  "status": "open",
  "province": "Ontario",
  "maxItems": 25,
  "includeDetails": true,
  "requestDelayMs": 150
}
````

To reuse a search configured on Biddingo:

```json
{
  "searchUrls": [
    { "url": "https://www.biddingo.com/search?keywords=construction&statuses=1" }
  ],
  "maxItems": 50,
  "includeDetails": true
}
```

### Output example

```json
{
  "biddingoTenderId": "41625328",
  "procurementId": "577294",
  "solicitationNumber": "Q26-81",
  "title": "David Durward Centre Roof Replacement",
  "buyerName": "City of Cambridge",
  "region": "Eastern Canada",
  "country": "Canada",
  "province": "Ontario",
  "city": "Cambridge",
  "postedDate": "2026-07-15",
  "closingDate": "2026-07-31",
  "closingTimeZone": "ET",
  "status": "Open for Bidding",
  "bidType": "Goods, Service, Construction",
  "categories": ["Construction", "Roofing Supplies/ Services"],
  "hasAddendum": false,
  "hasQna": false,
  "hasSiteMeeting": false,
  "hasResult": false,
  "hasAward": false,
  "isResearchBid": false,
  "isMasked": false,
  "detailUrl": "https://www.biddingo.com/dashboard/bid/1/11003134/41625328/verification"
}
```

Actual fields vary because Biddingo buyers decide which public details to provide.

### How much does it cost to scrape Biddingo tenders?

This Actor uses pay-per-event pricing.

A small one-time start event covers run setup, followed by one result event per saved tender.

The provisional base prices are:

- Start: **$0.005 per run**
- FREE result: **$0.000066261 per saved tender**
- BRONZE result: **$0.000057618 per saved tender**
- Higher usage tiers receive automatic volume discounts

At the BRONZE rate, a run saving 100 opportunities costs about **$0.0108** before any platform plan allowances.

Check the Actor pricing tab for the currently active tier and exact price.

### Tips for reliable tender monitoring

- Start with 10–25 records while refining keywords.
- Use source-specific words instead of broad phrases when precision matters.
- Keep detail enrichment on for lead qualification.
- Turn enrichment off for fast, listing-only market counts.
- Filter by province after the source search when you serve one territory.
- Use `offset` to partition large searches into separate tasks.
- Schedule daily open-opportunity runs to spot new notices.
- Deduplicate downstream by `biddingoTenderId`.
- Use `closingDate` and `daysLeft` to prioritize alerts.
- Treat `isMasked: true` as a source restriction, not missing scraper logic.

### Integrations and automation workflows

#### Daily email or Slack alerts

Schedule an Apify Task, compare IDs with the previous dataset, and send only new opportunities through a webhook.

#### CRM lead creation

Map `buyerName`, `title`, `province`, `closingDate`, and `detailUrl` into opportunity records in HubSpot, Salesforce, or another CRM.

#### Google Sheets bid calendar

Export records to Sheets and sort by `closingDate` and `daysLeft` for a shared estimator calendar.

#### Data warehouse ingestion

Fetch dataset items through the API and upsert by `biddingoTenderId` into BigQuery, Snowflake, PostgreSQL, or DuckDB.

#### Addendum watch

Run the same source URLs daily and trigger a workflow when `hasAddendum` or `addendumCount` changes.

### Use the Biddingo scraper API

#### JavaScript / Node.js

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/biddingo-public-tenders-scraper').call({
  keywords: 'roofing',
  province: 'Ontario',
  status: 'open',
  maxItems: 25,
  includeDetails: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/biddingo-public-tenders-scraper').call(run_input={
    'keywords': 'snow removal',
    'status': 'open',
    'maxItems': 25,
    'includeDetails': True,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~biddingo-public-tenders-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":"construction","status":"open","maxItems":25,"includeDetails":true}'
```

### Use Biddingo tender data through MCP

Apify MCP lets Claude Code and compatible clients run this Actor as a tool.

#### Claude Code

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/biddingo-public-tenders-scraper"
```

#### Claude Desktop, Cursor, or VS Code

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/biddingo-public-tenders-scraper"
    }
  }
}
```

Example prompts:

- “Find 20 open Ontario roofing tenders on Biddingo and sort them by closing date.”
- “Create a table of public buyers, cities, deadlines, and source links for snow removal opportunities.”
- “Show Biddingo opportunities with site meetings or addenda and fewer than 14 days left.”

### Scheduling a Biddingo opportunity monitor

1. Save a tested input as an Apify Task.
2. Add a daily or weekday schedule.
3. Keep `status` set to `open`.
4. Send the dataset ID to your integration or webhook.
5. Compare `biddingoTenderId` values with the previous run.
6. Alert only on new IDs or changed addendum/result flags.

Scheduled runs are useful because procurement opportunities and deadlines change continuously.

### Data quality and limitations

Biddingo controls the source data and can change its anonymous API.

Some records contain more details than others.

Some researched listings deliberately mask the buyer or solicitation number with values such as `OXOXOXOX`.

The Actor preserves those rows and sets `isResearchBid` or `isMasked`.

It does not bypass masking, authentication, subscription requirements, document fees, or buyer submission portals.

Date filters are applied to public normalized dates.

Text filters are case-insensitive substring filters after records are received.

An individual detail failure does not discard an otherwise useful listing record.

### Is scraping Biddingo legal?

This Actor accesses anonymous public listing and detail data without logging in.

Public procurement facts are generally business information, but legality depends on your jurisdiction, purpose, volume, and obligations.

You are responsible for:

- following applicable laws and contractual terms
- respecting intellectual-property and database rights
- using contact details for a lawful procurement purpose
- avoiding spam or discriminatory automated decisions
- setting a reasonable request rate
- securing exported datasets

Do not use the Actor to obtain paid documents or restricted account data.

### Troubleshooting

#### The dataset is empty

Remove buyer, location, and date filters first.

Test a broad keyword such as `construction`, or leave the keyword empty for the newest open opportunities.

Also confirm that a supplied URL belongs to Biddingo and uses the `/search` route.

#### I see masked buyer or solicitation values

That is expected for some Biddingo researched records.

Check `isResearchBid` and `isMasked`; the Actor intentionally does not invent or unlock restricted data.

#### A listing has no description or categories

Enable `includeDetails`.

If it is already enabled, the buyer may not expose those fields publicly or the detail request may have failed while the listing was preserved.

#### Large runs are slow

Turn off detail enrichment for a listing-only feed, reduce `requestDelayMs` carefully, or partition the search with `offset`.

### Related public tender scrapers

- [CanadaBuys Tender Opportunities Scraper](https://apify.com/automation-lab/canadabuys-tender-opportunities-scraper) — official Canadian federal procurement opportunities
- [Singapore GeBIZ Tender Opportunities Scraper](https://apify.com/automation-lab/singapore-gebiz-tender-opportunities-scraper) — Singapore government tenders and quotations
- [UK Find a Tender Scraper](https://apify.com/automation-lab/uk-find-a-tender-scraper) — UK high-value procurement notices
- [TED Europa Tenders Scraper](https://apify.com/automation-lab/ted-europa-tenders-scraper) — European public procurement notices
- [BOAMP Public Tenders Scraper](https://apify.com/automation-lab/boamp-public-tenders-scraper) — French public tenders
- [World Bank Procurement Notices Scraper](https://apify.com/automation-lab/world-bank-procurement-notices-scraper) — international development procurement

Choose the actor matching the source your team monitors; use several actors when you need broader geographic coverage.

### FAQ

#### Does this Actor require a Biddingo account?

No. The supported listing and detail fields are anonymously public.

#### Does it download tender documents?

No. Paid document downloads and subscription-only enrichment are deliberately excluded.

#### Can I provide a Biddingo search URL?

Yes. Add one or more `https://www.biddingo.com/search?...` URLs to `searchUrls`.

#### Can I scrape all current opportunities?

Set a larger `maxItems` and leave `keywords` empty. Use a polite delay and consider partitioning with offsets.

#### Can I run it every day?

Yes. A scheduled task is one of the main use cases; deduplicate by `biddingoTenderId`.

#### Why are some optional fields missing?

Different buyers publish different detail levels, and researched records can be intentionally masked by Biddingo.

#### What export formats are available?

Apify datasets support JSON, CSV, Excel, XML, RSS, and Parquet exports.

#### How should I identify urgent bids?

Sort or filter by `closingDate` and `daysLeft`, then inspect site-meeting and addendum flags.

### Support

If a run behaves unexpectedly, share its Apify run URL and a redacted copy of the input through the Actor issue form.

Include the keyword or search URL, expected opportunity, and whether detail enrichment was enabled.

That evidence makes source changes and edge cases much faster to diagnose.

# Actor input Schema

## `keywords` (type: `string`):

Search tender titles and public bid content. Leave empty to collect the newest opportunities.

## `searchUrls` (type: `array`):

Optional https://www.biddingo.com/search URLs. Each URL becomes a separate search and overrides the generated keyword search.

## `status` (type: `string`):

Collect open opportunities only, or request all statuses available from Biddingo.

## `buyer` (type: `string`):

Keep opportunities whose public buyer name contains this text.

## `region` (type: `string`):

Keep opportunities in a Biddingo region such as Eastern Canada or Western Canada.

## `province` (type: `string`):

Keep opportunities whose province contains this text, for example Ontario or Alberta.

## `city` (type: `string`):

Keep opportunities whose public city contains this text.

## `postedAfter` (type: `string`):

Keep opportunities posted on or after this date (YYYY-MM-DD).

## `closingBefore` (type: `string`):

Keep opportunities closing on or before this date (YYYY-MM-DD).

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

Maximum unique Biddingo tender records to save across all searches.

## `offset` (type: `integer`):

Start at this Biddingo result offset. Use with maxItems to resume or partition large searches.

## `includeDetails` (type: `boolean`):

Request each anonymous public detail endpoint for descriptions, categories, contacts, and richer flags. No paid documents are downloaded.

## `requestDelayMs` (type: `integer`):

Polite delay between Biddingo API requests. Increase this value for very large enriched runs.

## Actor input object example

```json
{
  "keywords": "roofing",
  "searchUrls": [],
  "status": "open",
  "buyer": "",
  "region": "",
  "province": "",
  "city": "",
  "postedAfter": "",
  "closingBefore": "",
  "maxItems": 10,
  "offset": 0,
  "includeDetails": true,
  "requestDelayMs": 150
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "keywords": "roofing",
    "searchUrls": [],
    "status": "open",
    "buyer": "",
    "region": "",
    "province": "",
    "city": "",
    "postedAfter": "",
    "closingBefore": "",
    "maxItems": 10,
    "offset": 0,
    "includeDetails": true,
    "requestDelayMs": 150
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/biddingo-public-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 = {
    "keywords": "roofing",
    "searchUrls": [],
    "status": "open",
    "buyer": "",
    "region": "",
    "province": "",
    "city": "",
    "postedAfter": "",
    "closingBefore": "",
    "maxItems": 10,
    "offset": 0,
    "includeDetails": True,
    "requestDelayMs": 150,
}

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

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

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

```

## CLI example

```bash
echo '{
  "keywords": "roofing",
  "searchUrls": [],
  "status": "open",
  "buyer": "",
  "region": "",
  "province": "",
  "city": "",
  "postedAfter": "",
  "closingBefore": "",
  "maxItems": 10,
  "offset": 0,
  "includeDetails": true,
  "requestDelayMs": 150
}' |
apify call automation-lab/biddingo-public-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/biddingo-public-tenders-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Biddingo Public Tenders Scraper",
        "description": "🇨🇦 Find public Biddingo tenders with buyers, locations, deadlines, descriptions, addenda, Q&A, submission, result, and award indicators.",
        "version": "0.1",
        "x-build-id": "titEuK3Z1QukVpDxr"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~biddingo-public-tenders-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-biddingo-public-tenders-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/automation-lab~biddingo-public-tenders-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-biddingo-public-tenders-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/automation-lab~biddingo-public-tenders-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-biddingo-public-tenders-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "keywords": {
                        "title": "Tender keywords",
                        "type": "string",
                        "description": "Search tender titles and public bid content. Leave empty to collect the newest opportunities.",
                        "default": ""
                    },
                    "searchUrls": {
                        "title": "Biddingo search URLs",
                        "type": "array",
                        "description": "Optional https://www.biddingo.com/search URLs. Each URL becomes a separate search and overrides the generated keyword search.",
                        "default": [],
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "status": {
                        "title": "Opportunity status",
                        "enum": [
                            "open",
                            "all"
                        ],
                        "type": "string",
                        "description": "Collect open opportunities only, or request all statuses available from Biddingo.",
                        "default": "open"
                    },
                    "buyer": {
                        "title": "Buyer contains",
                        "type": "string",
                        "description": "Keep opportunities whose public buyer name contains this text.",
                        "default": ""
                    },
                    "region": {
                        "title": "Biddingo region contains",
                        "type": "string",
                        "description": "Keep opportunities in a Biddingo region such as Eastern Canada or Western Canada.",
                        "default": ""
                    },
                    "province": {
                        "title": "Province contains",
                        "type": "string",
                        "description": "Keep opportunities whose province contains this text, for example Ontario or Alberta.",
                        "default": ""
                    },
                    "city": {
                        "title": "City contains",
                        "type": "string",
                        "description": "Keep opportunities whose public city contains this text.",
                        "default": ""
                    },
                    "postedAfter": {
                        "title": "Posted on or after",
                        "pattern": "^$|^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Keep opportunities posted on or after this date (YYYY-MM-DD).",
                        "default": ""
                    },
                    "closingBefore": {
                        "title": "Closing on or before",
                        "pattern": "^$|^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Keep opportunities closing on or before this date (YYYY-MM-DD).",
                        "default": ""
                    },
                    "maxItems": {
                        "title": "Maximum tenders",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum unique Biddingo tender records to save across all searches.",
                        "default": 20
                    },
                    "offset": {
                        "title": "Starting offset",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Start at this Biddingo result offset. Use with maxItems to resume or partition large searches.",
                        "default": 0
                    },
                    "includeDetails": {
                        "title": "Enrich public bid details",
                        "type": "boolean",
                        "description": "Request each anonymous public detail endpoint for descriptions, categories, contacts, and richer flags. No paid documents are downloaded.",
                        "default": true
                    },
                    "requestDelayMs": {
                        "title": "Delay between requests (ms)",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Polite delay between Biddingo API requests. Increase this value for very large enriched runs.",
                        "default": 150
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
