UK Public Contracts Lookup: Find a Tender and Contracts Finder avatar

UK Public Contracts Lookup: Find a Tender and Contracts Finder

Pricing

from $5.00 / 1,000 notices

Go to Apify Store
UK Public Contracts Lookup: Find a Tender and Contracts Finder

UK Public Contracts Lookup: Find a Tender and Contracts Finder

Search, look up and monitor UK public procurement notices from Find a Tender and Contracts Finder (Public Contracts Scotland opt-in) in one fixed row per notice. Official data under the OGL, built to hold no personal data. Pay per event: $0.005 a notice plus $0.005 a run.

Pricing

from $5.00 / 1,000 notices

Rating

0.0

(0)

Developer

Russell Yapp

Russell Yapp

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 hours ago

Last modified

Categories

Share

UK Public Contracts Lookup: Find a Tender and Contracts Finder notices in one schema

You get official UK public procurement notices from Find a Tender and Contracts Finder (and Public Contracts Scotland if you choose it), one fixed row per notice, built to hold no personal data.

publishedAtsourcetitlebuyervaluecurrencystagedeadlineregions
2026-09-09T00:00:00ZftsChildren Affected by Parental Offending - Expression of InterestBristol City Council80000GBPtender2026-09-30T11:00:00ZSouth West

A default run (search, the last 31 days, both default services, with maxItems prefilled at 20) returns the 20 newest notices, usually in under a minute and at most about 3, and costs $0.105: $0.005 for the run and $0.005 a notice. Raise maxItems in the input, up to 100,000, to get more.

Run it with the default input.

41-second demo on YouTube: https://youtu.be/sf8TcgO2wis

What you get

One row per notice, the same fields for every service. A missing value is null (or [] for lists), never an absent key.

FieldTypeMeaning
source"fts", "cf" or "pcs"The service the notice came from: Find a Tender, Contracts Finder or Public Contracts Scotland
noticeIdstringFind a Tender id (094494-2026), Contracts Finder notice GUID, or Public Contracts Scotland notice id (SEP565172; SEP564648-1 for a notice split into lots)
ocidstring or nullThe contracting-process id. null for Find a Tender legacy forms read from bulk files, which carry no OCID. Every pcs row carries its OCID
relatedOcidsarray of stringsOCIDs of the same procurement on another service, taken only from explicit references in the notice. Nearly always []
reconcileKeystring or nullProbably the same procurement: join it yourself. A hash of the normalised buyer and title; two rows with the same key, from different services, are likely one procurement. It misses pairs worded differently, and generic titles from one buyer can collide. null if buyer or title is empty
releaseIdstringId of the notice version returned (Find a Tender: the notice id; Contracts Finder: {guid}-{n}, the latest; Public Contracts Scotland: the same as noticeId)
titlestring or nullNotice title, with personal details redacted. null for follow-up notices that have no title of their own
buyerstring or nullBuyer organisation name only
valuenumber or nullEstimated value; for award and contract notices, the sum of the awarded or contracted amounts. null where currencies are mixed. As published, including placeholders
currencystring or nullISO 4217 code of value
cpvCodesarray of stringsEvery CPV code on the notice, 8 digits, de-duplicated and sorted
regionsarray of stringsUK ITL1 regions of delivery, or Outside UK. A UK-wide location lists all twelve regions
publishedAtstringPublication time (ISO 8601, UTC) of the version returned. For Find a Tender legacy forms read from bulk files it is the date at T00:00:00Z. For pcs rows it is almost always a date at midnight UTC, because Public Contracts Scotland publishes dates, not times (quick quote awards are the exception)
deadlinestring or nullTender deadline (ISO 8601, UTC); null if none or unreadable
stagestringplanning, tender, award, contract or termination
noticeUrlstringThe public notice page (for pcs, on publiccontractsscotland.gov.uk)
alertFingerprintstring or nullSet only in alert mode; null otherwise

Illustrative row (the values are made up):

{
"source": "fts",
"noticeId": "012345-2026",
"ocid": "ocds-h6vhtk-0a1b2c",
"relatedOcids": [],
"reconcileKey": "3f9a1c7e5b2d4a60",
"releaseId": "012345-2026",
"title": "Highways Maintenance Framework",
"buyer": "Example County Council",
"value": 4500000,
"currency": "GBP",
"cpvCodes": ["45233141", "50230000"],
"regions": ["North West"],
"publishedAt": "2026-10-06T09:30:00Z",
"deadline": "2026-11-13T12:00:00Z",
"stage": "tender",
"noticeUrl": "https://www.find-tender.service.gov.uk/Notice/012345-2026",
"alertFingerprint": null
}

Rows come out newest publishedAt first, then by source and notice id, so the same input on the same data gives the same order.

Modes

sources (default ["fts","cf"]) chooses which service to read. Public Contracts Scotland is opt-in and is read only when chosen: "sources": ["pcs"], or ["fts","cf","pcs"] for all three. A procurement published on two services is two notices and two rows.

{
"mode": "search",
"keywords": ["bridge"],
"cpvCodes": ["45"],
"regions": ["Scotland"],
"deadlineFrom": "2026-10-07",
"maxItems": 200
}
  • Window: publishedFrom and publishedTo (UTC days, inclusive). Default is 31 days: today and the 30 days before. Maximum 92 days. A longer window is refused before anything is read, and nothing is charged. A publishedTo in the future counts as today.
  • Filters are combined with AND; within a list, any match counts.
    • buyers: case-insensitive part of the buyer name.
    • keywords: whole words in the title and description. The description is matched but never returned.
    • cpvCodes: prefixes. 72 matches all of division 72; 72212000 matches itself and the codes beneath it.
    • valueMin, valueMax: GBP. Notices in another currency or without a value are left out when either is set.
    • regions: the 12 UK ITL1 regions, plus Outside UK.
    • stages: planning, tender, award, contract, termination.
    • deadlineFrom: deadline on or after this day. Notices without a deadline are left out when it is set.
    • maxItems: hard cap on rows and so on charges. Prefilled at 20 in the input form. When it is left out, as in an API call with no maxItems, it is 1,000.

Lookup

{
"mode": "lookup",
"noticeIds": ["094494-2026"]
}
  • Up to 20 ids per run: a Find a Tender notice id, a Find a Tender OCID (its latest notice is returned), a Contracts Finder notice GUID, or a Public Contracts Scotland OCID. Contracts Finder OCIDs are not supported.
  • A Public Contracts Scotland OCID is ocds-r6ebe6- plus 10 digits (for example ocds-r6ebe6-0000845164), optionally with a lot suffix such as -1. A Public Contracts Scotland notice id such as SEP565172 cannot be looked up, because its API has no call for it: it is refused with a message asking for the OCID. Every pcs row carries its OCID, so take it from there.
  • An id that is not found gives no row and no charge, and is listed in RUN_SUMMARY.notFound.
  • If a source rate-limits the run, lookup stops at once. Ids already found are returned; every id not yet looked up is listed in RUN_SUMMARY.retryAfter as seconds, until and ids, with no row and no charge for them. The run itself succeeds, so a script or agent can read the summary and retry after until.

Alert

{
"mode": "alert",
"alertId": "highways-north-west",
"keywords": ["highway"],
"regions": ["North West"],
"firstRunLookbackDays": 1
}
  • alertId is yours to choose: lower-case letters, digits and hyphens, 1 to 40 characters.
  • State is kept in a key-value store named contracts-alert-<alertId> in your own Apify account.
  • Each run looks at the last 14 days of notices. Anything that matches your filters and is not already in the store is new, so a notice that reached the source late is still caught.
  • First run: notices from the last firstRunLookbackDays days (default 1, maximum 14) are returned and charged. The rest of the 14-day window is recorded as already seen, without charge.
  • Each notice is sent once per alertId. A Contracts Finder amendment is not sent again. A Find a Tender award or change is its own notice with its own id, so it is new. Changing the filters keeps the store, so nothing already sent comes back.
  • A second run for the same alertId that starts while one is active stops before reading anything and charges nothing; its summary says locked.
  • Safe to schedule daily.

Pricing

Pay per event. Platform usage is included, so this is what you pay.

EventChargedPrice, the same on every plan
runOnce per run that read data$0.005
noticeEach row returned$0.005 ($5.00 per 1,000)

Runs refused before anything is read cost nothing: a window over 92 days, invalid input, a lookup rate-limited before any answer, or an alert that finds its store locked. "Not found" counts as read, because the source answered.

Notices from Public Contracts Scotland are charged as notice events like the others, and its answers count as data read for the run event.

Typical costs: looking up one notice costs $0.01; a daily alert returning about 20 new notices costs about $0.105 a run. Cap spend with maxItems and with Apify's maximum-charge setting on the run; if the cap is reached the summary reports chargeLimitReached.

Freshness and coverage

  • Bulk files first. Find a Tender and Contracts Finder each publish one file per day, the day after: Find a Tender at about 03:05 UTC, Contracts Finder at about 02:00 UTC. Days with a file are read from it, with no API call.
  • APIs for the gap. Today, and any day whose file is missing, comes from the service API. (This does not apply to Public Contracts Scotland, below.)
  • When the source limits the run, the run still finishes from what it has read. RUN_SUMMARY.sources.<source>.staleSince is the first day not covered, and missingDays lists them. An alert picks those notices up on its next run.
  • Later versions. A notice first published inside your window can carry a later publishedAt if a newer version has since been published; the row is returned and counted in laterVersions.
  • Public Contracts Scotland has no bulk files. It is read as month lists: one list per notice type per month (21 types), so a search reads every notice type for each month the window touches. A window spanning 2 months is 42 lists and one spanning 4 months is 84. Large lists are slow; when measured, one month's 21 lists took about 3.5 minutes of response time plus about 1 minute of pacing, so a search that includes pcs takes minutes longer.
  • A past month's list can fail on the first request. The Actor tries each list three times, 30 seconds apart. A list that still fails is named in RUN_SUMMARY.sources.pcs.missingLists (for example 2026-09:102, month and notice type), never silently dropped, and the run finishes from everything else.
  • Find a Tender is currently read from its API only. The Find a Tender bulk files are not used yet, so wide Find a Tender searches can come back partial, and sources.fts.missingDays says which days are missing. In alert mode, Find a Tender is read from the day of the alert's last complete run (re-reading that day, so nothing published later that day is missed) instead of the full 14 days. Contracts Finder is unaffected.

Run summary

Every run writes a RUN_SUMMARY record to its key-value store. Main fields:

FieldMeaning
statusok, refused (input rejected; reason says why; the run fails and nothing is charged) or locked (alert already running)
pushedRows returned
readDataWhether the run read any data
runChargedWhether the run event was charged
sources.fts, sources.cfPer service: bulkDays, apiDays, missingDays, staleSince, noticesRead. In alert mode these sit under search.sources
sources.pcsPublic Contracts Scotland: listsRead and missingLists (month lists that could not be read, as YYYY-MM:type). In alert mode this sits under search.sources
apiAPI use: requests, answers, budget, refusals, waitedSeconds, stopped, retryAfter (seconds)
pcsApiThe same kind of API use figures, for Public Contracts Scotland, which has its own client and pacing
retryAfterLookup only: seconds, until, ids still to look up
notFoundLookup only: ids that returned nothing
laterVersionsRows whose publishedAt is after your window
followUpsCompleted, followUpsWithoutTitleFollow-up notices that borrowed a title and buyer from another row with the same OCID in the run, and those that found none

Data and licence

  • Each service's notice data is published under the Open Government Licence v3.0. Public Contracts Scotland data is published by the Scottish Government (Scottish Procurement and Commercial Directorate) under the same licence. Please keep this attribution: Contains public sector information licensed under the Open Government Licence v3.0.
  • Rows are built to hold no personal data: they hold no contact names, emails, phone numbers, addresses, supplier names or descriptions. In titles, email addresses, UK phone numbers and a person's name written straight after "contact", "speak to", "email", "FAO", "attention of" or "write to" are replaced with [redacted]. That redaction works by pattern, so a name written some other way in a title is not caught.
  • Official sources only: Find a Tender, Contracts Finder and Public Contracts Scotland. No proxies are used.

Limits

  • Search window: 31 days by default, 92 days at most.
  • Lookup: 20 ids per run.
  • Alert: 14-day window; firstRunLookbackDays 1 to 14.
  • maxItems: prefilled at 20, 1,000 when left out, maximum 100,000. A search reads only the days it needs: once it has maxItems notices newer than a day still to be fetched from an API, that day and older ones are skipped, because they could not appear in the newest-first result.
  • Scottish duplicates: an above-threshold Scottish notice can appear as both a pcs row and an fts row. That is two rows and two charges; join them with reconcileKey.
  • pcs dates: publishedAt is almost always a date only (midnight UTC), so Public Contracts Scotland rows are day-precise, not time-precise.
  • API pacing: Find a Tender and Contracts Finder share one rate limiter, so the Actor makes at most one API request every 15 seconds, across both. Public Contracts Scotland is a different host with its own pacing: one request every 3 seconds, and a refusal from one client does not stop the other.
  • Public Contracts Scotland request budget: months touched × 21, plus 10 (a 92-day window touches up to 5 months). An alert's 14-day window touches 1 or 2 months, read in full on every run. Reading Public Contracts Scotland stops after 40 minutes in any run; lists not read by then are named in missingLists.
  • Request budget per run: lookup makes one request per id (20 ids takes about 5 minutes). Searches and alerts have a fixed cap on API requests: 12 a run, plus 36 while Find a Tender is API-only. Those 36 take about 9 minutes and cover roughly the last 8 days of Find a Tender. When the cap is reached the run ends normally and reports the days it did not cover.
  • The input takes no URLs, headers or query strings: the Actor builds every request itself.