UK Public Contracts Lookup: Find a Tender and Contracts Finder
Pricing
from $5.00 / 1,000 notices
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
Maintained by CommunityActor 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.
| publishedAt | source | title | buyer | value | currency | stage | deadline | regions |
|---|---|---|---|---|---|---|---|---|
| 2026-09-09T00:00:00Z | fts | Children Affected by Parental Offending - Expression of Interest | Bristol City Council | 80000 | GBP | tender | 2026-09-30T11:00:00Z | South 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.
| Field | Type | Meaning |
|---|---|---|
source | "fts", "cf" or "pcs" | The service the notice came from: Find a Tender, Contracts Finder or Public Contracts Scotland |
noticeId | string | Find a Tender id (094494-2026), Contracts Finder notice GUID, or Public Contracts Scotland notice id (SEP565172; SEP564648-1 for a notice split into lots) |
ocid | string or null | The contracting-process id. null for Find a Tender legacy forms read from bulk files, which carry no OCID. Every pcs row carries its OCID |
relatedOcids | array of strings | OCIDs of the same procurement on another service, taken only from explicit references in the notice. Nearly always [] |
reconcileKey | string or null | Probably 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 |
releaseId | string | Id of the notice version returned (Find a Tender: the notice id; Contracts Finder: {guid}-{n}, the latest; Public Contracts Scotland: the same as noticeId) |
title | string or null | Notice title, with personal details redacted. null for follow-up notices that have no title of their own |
buyer | string or null | Buyer organisation name only |
value | number or null | Estimated value; for award and contract notices, the sum of the awarded or contracted amounts. null where currencies are mixed. As published, including placeholders |
currency | string or null | ISO 4217 code of value |
cpvCodes | array of strings | Every CPV code on the notice, 8 digits, de-duplicated and sorted |
regions | array of strings | UK ITL1 regions of delivery, or Outside UK. A UK-wide location lists all twelve regions |
publishedAt | string | Publication 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) |
deadline | string or null | Tender deadline (ISO 8601, UTC); null if none or unreadable |
stage | string | planning, tender, award, contract or termination |
noticeUrl | string | The public notice page (for pcs, on publiccontractsscotland.gov.uk) |
alertFingerprint | string or null | Set 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.
Search
{"mode": "search","keywords": ["bridge"],"cpvCodes": ["45"],"regions": ["Scotland"],"deadlineFrom": "2026-10-07","maxItems": 200}
- Window:
publishedFromandpublishedTo(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. ApublishedToin 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.72matches all of division 72;72212000matches 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, plusOutside 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 nomaxItems, 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 exampleocds-r6ebe6-0000845164), optionally with a lot suffix such as-1. A Public Contracts Scotland notice id such asSEP565172cannot be looked up, because its API has no call for it: it is refused with a message asking for the OCID. Everypcsrow 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.retryAfterasseconds,untilandids, with no row and no charge for them. The run itself succeeds, so a script or agent can read the summary and retry afteruntil.
Alert
{"mode": "alert","alertId": "highways-north-west","keywords": ["highway"],"regions": ["North West"],"firstRunLookbackDays": 1}
alertIdis 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
firstRunLookbackDaysdays (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
alertIdthat starts while one is active stops before reading anything and charges nothing; its summary sayslocked. - Safe to schedule daily.
Pricing
Pay per event. Platform usage is included, so this is what you pay.
| Event | Charged | Price, the same on every plan |
|---|---|---|
run | Once per run that read data | $0.005 |
notice | Each 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>.staleSinceis the first day not covered, andmissingDayslists them. An alert picks those notices up on its next run. - Later versions. A notice first published inside your window can carry a later
publishedAtif a newer version has since been published; the row is returned and counted inlaterVersions. - 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
pcstakes 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 example2026-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.missingDayssays 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:
| Field | Meaning |
|---|---|
status | ok, refused (input rejected; reason says why; the run fails and nothing is charged) or locked (alert already running) |
pushed | Rows returned |
readData | Whether the run read any data |
runCharged | Whether the run event was charged |
sources.fts, sources.cf | Per service: bulkDays, apiDays, missingDays, staleSince, noticesRead. In alert mode these sit under search.sources |
sources.pcs | Public Contracts Scotland: listsRead and missingLists (month lists that could not be read, as YYYY-MM:type). In alert mode this sits under search.sources |
api | API use: requests, answers, budget, refusals, waitedSeconds, stopped, retryAfter (seconds) |
pcsApi | The same kind of API use figures, for Public Contracts Scotland, which has its own client and pacing |
retryAfter | Lookup only: seconds, until, ids still to look up |
notFound | Lookup only: ids that returned nothing |
laterVersions | Rows whose publishedAt is after your window |
followUpsCompleted, followUpsWithoutTitle | Follow-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;
firstRunLookbackDays1 to 14. maxItems: prefilled at 20, 1,000 when left out, maximum 100,000. A search reads only the days it needs: once it hasmaxItemsnotices 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
pcsrow and anftsrow. That is two rows and two charges; join them withreconcileKey. pcsdates:publishedAtis 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.