{
  "openapi": "3.0.1",
  "info": {
    "title": "World Bank Tenders, Contract Awards & Bid Deadlines",
    "description": "Tender notices and contract awards of World Bank-financed projects as rows: what is bought, the bid deadline in UTC with days left, borrower country, project, procurement method, reference number and the notice text. Filter by keyword, country, notice type or method. Keyless official API.",
    "version": "0.1",
    "x-build-id": "y9TvGknM6FoIx3s5j"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/yadroo~world-bank-procurement/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-yadroo-world-bank-procurement",
        "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/yadroo~world-bank-procurement/runs": {
      "post": {
        "operationId": "runs-sync-yadroo-world-bank-procurement",
        "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/yadroo~world-bank-procurement/run-sync": {
      "post": {
        "operationId": "run-sync-yadroo-world-bank-procurement",
        "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": {
          "mode": {
            "title": "What to fetch",
            "enum": [
              "notices",
              "awards",
              "all"
            ],
            "type": "string",
            "description": "Two different questions out of one source. `notices` keeps the four opportunity types (invitation for bids, request for expression of interest, general procurement notice, invitation for prequalification) and is what a bidder wants: these rows carry a submission deadline. `awards` keeps the contract-award records, the history of who won which contract on a financed project; those rows have no deadline and the winner, the amount and the scoring live inside `noticeText`, because the source publishes them as notice text and not as separate fields. `all` mixes both and is useful when you follow one project from first notice to signed contract. The mode only presets `noticeTypes`; set that field yourself to be precise.",
            "default": "notices"
          },
          "query": {
            "title": "Keyword",
            "type": "string",
            "description": "Free-text search over the notice - the bid description, the project name and the full notice text. One word (`solar`, `hospital`, `dredging`) behaves the way you expect. Several words are treated by the source as \"any of these words\", which is why `water supply` alone matches over 80 000 notices; `queryMatch` below turns that into \"all of these words\" for you. Leave empty to browse a country, a project or a date window without a keyword."
          },
          "queryMatch": {
            "title": "How to match several keywords",
            "enum": [
              "all",
              "any"
            ],
            "type": "string",
            "description": "Only matters for a multi-word `query`. `all` filters the fetched rows down to the ones whose bid description, project name or notice text contains every word, case-insensitively - a two-word query then returns the handful of relevant notices instead of tens of thousands. `any` writes what the source returned, unfiltered. A word may sit in the notice text rather than in the short description, so a row can match without the word being visible in `bidDescription`.",
            "default": "all"
          },
          "countries": {
            "title": "Countries",
            "type": "array",
            "description": "Country names as the source spells them, e.g. [\"Kazakhstan\"], [\"Nigeria\", \"Ghana\"], [\"Viet Nam\"], [\"Congo, Democratic Republic of\"]. Combined with OR. Letter case and punctuation do not matter (\"St Lucia\" is \"St. Lucia\"), and common names are translated (\"Egypt\", \"Iran\", \"DRC\", \"Ivory Coast\"); every translation is named in the run status. Anything else stops the run before a request is sent, with \"did you mean\" - a near miss is never swapped for the closest label, because Niger and Nigeria are one letter apart. Mind `countryField`: many notices belong to a regional project whose country field reads \"Central Asia\", \"Western and Central Africa\" or \"Eastern and Southern Africa\" even though the buyer sits in one country. README > Reference lists every country and regional label.",
            "items": {
              "type": "string"
            }
          },
          "countryField": {
            "title": "Which country field to match",
            "enum": [
              "either",
              "project",
              "implementing"
            ],
            "type": "string",
            "description": "The source carries two countries per notice: the project country, which for a regional programme is a region and not a country, and the country of the contact agency that actually buys. Kazakhstan is a clear case: about 850 notices are booked under \"Kazakhstan\" and about 400 more under the regional label \"Central Asia\" with a Kazakh agency as the buyer. `either` sends both queries and removes duplicates by notice id, so you see all of them; `project` and `implementing` restrict to one side. The name that matched is repeated in the `matchedCountry` output field.",
            "default": "either"
          },
          "noticeTypes": {
            "title": "Notice types",
            "type": "array",
            "description": "Empty follows `mode`. Set it to override the mode, e.g. only [\"Request for Expression of Interest\"] for consulting work, or [\"General Procurement Notice\"] to see what a project plans to buy months before the tender. One request per type is sent and the results are merged.",
            "items": {
              "type": "string",
              "enum": [
                "Invitation for Bids",
                "Request for Expression of Interest",
                "General Procurement Notice",
                "Invitation for Prequalification",
                "Contract Award"
              ],
              "enumTitles": [
                "Invitation for Bids - a concrete tender open for offers",
                "Request for Expression of Interest - consultants asked to apply",
                "General Procurement Notice - early notice of what a project will buy",
                "Invitation for Prequalification - bidders qualified before the tender",
                "Contract Award - a contract that has been awarded"
              ]
            }
          },
          "procurementGroups": {
            "title": "What is procured",
            "type": "array",
            "description": "The source's own four categories, combined with OR. This is the cheapest way to split a market: a construction company wants CW, an equipment supplier GO, an engineering firm CS. The readable label is added to every row as `procurementGroupName`.",
            "items": {
              "type": "string",
              "enum": [
                "GO",
                "CS",
                "CW",
                "NC"
              ],
              "enumTitles": [
                "GO - goods (equipment, vehicles, supplies)",
                "CS - consulting services (studies, design, supervision)",
                "CW - civil works (construction)",
                "NC - non-consulting services (transport, printing, maintenance)"
              ]
            }
          },
          "procurementMethods": {
            "title": "Procurement method codes",
            "type": "array",
            "description": "Method codes as the source writes them (any letter case), combined with OR. Current framework: RFB request for bids, RFQ request for quotations, RFP request for proposals, QCBS quality and cost-based selection, FBS fixed budget selection, LCS least cost selection, CQS consultant qualification selection, INDV individual consultant selection, CDS and DIR direct selection. Notices from before the 2016 framework use the older codes, e.g. ICB international competitive bidding (about 16 000 rows), NCB national competitive bidding, SSS single-source selection. Any other value stops the run with the list of codes - a partial code such as \"IC\" is not read as ICB. The readable name is in `procurementMethodName`; leave the field empty unless you know which methods matter to you.",
            "items": {
              "type": "string"
            }
          },
          "projectIds": {
            "title": "Project ids",
            "type": "array",
            "description": "World Bank project ids, e.g. [\"P177816\"], [\"P171577\", \"P179008\"]. Combined with OR. Returns every notice and award of that project, which is how you follow one financed programme over years - a large programme has hundreds of rows. An id the source does not know yields one row with `found` = false that says so, never an empty success; a value that is not an id (the letter P and five to seven digits) stops the run.",
            "items": {
              "type": "string"
            }
          },
          "languages": {
            "title": "Notice language",
            "type": "array",
            "description": "Keep notices published in these languages. Most notices are English; French, Spanish and Portuguese appear for West and Central Africa, Latin America and Lusophone countries. The source stores the Spanish label with its cataloguing suffix, which is why the value looks unusual.",
            "items": {
              "type": "string",
              "enum": [
                "English",
                "French",
                "Spanish; Castilian",
                "Portuguese"
              ],
              "enumTitles": [
                "English",
                "French",
                "Spanish (the source stores the label \"Spanish; Castilian\")",
                "Portuguese"
              ]
            }
          },
          "onlyOpen": {
            "title": "Only notices whose deadline has not passed",
            "type": "boolean",
            "description": "Keep only rows whose submission deadline is still in the future at run time, compared in UTC. This is the filter a bidder wants and the source has no equivalent, so the actor walks the notices in deadline order and stops when the deadlines fall into the past. Rows without a deadline (contract awards, most general procurement notices) are dropped by this switch, so leave it off when you study history.",
            "default": false
          },
          "deadlineWithinDays": {
            "title": "Deadline within the next N days",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Keep only notices whose deadline falls between now and N days from now, e.g. 14 for \"what closes in the next two weeks\". Implies the open-deadline filter above. Leave empty for no upper bound."
          },
          "sinceDays": {
            "title": "Published in the last N days",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Keep only notices published in the last N days, by the notice date. 1 gives yesterday's and today's batch, 7 a weekly digest, 30 a month. This is the window to use for a scheduled run: with it the actor pages by notice date and stops at the edge of the window, so a daily run costs two or three requests."
          },
          "onlyNew": {
            "title": "Only notices not seen in an earlier run",
            "type": "boolean",
            "description": "Remember the notice ids this filter set has written, in a named key-value store of your account, and write only ids that were not written before. Turns a schedule into an alert feed: the first run returns the current window, later runs return only what appeared since. Only rows really written are remembered (a run stopped by your max cost per run does not lose the rest). A run that finds nothing new writes no row and says so in its status. Independent of `sinceDays` - combine them, because the memory is what prevents duplicates while the window keeps the run cheap.",
            "default": false
          },
          "sort": {
            "title": "Row order",
            "enum": [
              "noticeDateDesc",
              "noticeDateAsc",
              "deadlineAsc",
              "deadlineDesc"
            ],
            "type": "string",
            "description": "Order of the rows in the dataset. Rows without a deadline sort last in the two deadline orders. When several filter values are merged the order is applied after the merge, so the dataset is sorted as a whole and not per request.",
            "default": "noticeDateDesc"
          },
          "maxItems": {
            "title": "Maximum rows",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Hard cap on the rows written, and on what you pay for. 25-50 answers a question, a few hundred fills a dashboard, and the whole index holds over 400 000 notices, so keep the cap and a filter in place. Without a window, paging stops as soon as the cap is reached; with `sinceDays`, `onlyOpen` or `deadlineWithinDays` the actor reads the window so that the rows it keeps are really the first ones in your order. Your max cost per run is a second cap: the run stops there and says so.",
            "default": 50
          },
          "maxRequests": {
            "title": "Maximum requests to the source",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Second guard, on the source side: the run stops after this many search requests even if the caps and windows above are not exhausted, and says so in the run status. It matters when a filter that the actor applies itself (all-words keyword, open deadline) throws most fetched rows away. Requests are sent one at a time, at least half a second apart. Raise it for a wide crawl, leave it for a monitoring run.",
            "default": 25
          },
          "includeNoticeText": {
            "title": "Include the notice text",
            "type": "boolean",
            "description": "Add the body of the notice as plain text with the source's HTML markup removed. For a tender this is the part that names the lots, the eligibility rules, the bid security and the address for submission; for a contract award it is the only place where the winning firm, the contract amount and the evaluation scores appear. Switch it off for narrow rows and a small dataset (a `fields` list without `noticeText` does the same).",
            "default": true
          },
          "noticeTextMaxChars": {
            "title": "Truncate the notice text at N characters",
            "minimum": 200,
            "maximum": 40000,
            "type": "integer",
            "description": "Upper bound on the plain text kept per row; some notices run to tens of thousands of characters. When a text is cut, `noticeTextTruncated` is true, so you can spot the rows where you need the full notice from its page.",
            "default": 4000
          },
          "fields": {
            "title": "Fields to keep",
            "type": "array",
            "description": "Keep only these output fields, in this order, e.g. [\"bidDescription\", \"submissionDeadline\", \"projectCountry\", \"url\"]. Empty returns every field. `rowType` (and `found` / `message` on a no-match row) is always kept. Letter case and snake_case are accepted; an unknown name is ignored and named in the run status, and a list with no valid name stops the run. Leaving `noticeText` out also skips fetching it. Field names are listed in README > Output.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}