UK Public Tenders incl. Scotland — FTS + CF + PCS avatar

UK Public Tenders incl. Scotland — FTS + CF + PCS

Pricing

from $5.00 / 1,000 notice delivereds

Go to Apify Store
UK Public Tenders incl. Scotland — FTS + CF + PCS

UK Public Tenders incl. Scotland — FTS + CF + PCS

Deduplicated UK procurement notices from three official public feeds, including Scottish site notices, local filters and incremental monitoring. No API key.

Pricing

from $5.00 / 1,000 notice delivereds

Rating

0.0

(0)

Developer

Biosick Johnny

Biosick Johnny

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Security

Limited permissions

Share

UK Public Tenders including Scotland

One OCDS-normalised feed from Find a Tender (FTS), Contracts Finder (CF), and Public Contracts Scotland (PCS). Combine official public notices, retain their provenance, apply procurement filters, and monitor changes without repeatedly delivering previously seen content versions.

The Scotland difference is practical: PCS site notices and Quick Quote awards provide Scottish below-threshold coverage that an FTS/CF-only feed misses. Exact Scottish reference matching joins notices published on both FTS and PCS, preferring PCS and retaining the FTS identity.

No source account, API key or login is needed. Price: $5 per 1,000 delivered notices plus $0.005 per run start. Source data itself is free.

Quick start

{
"sources": ["fts", "cf", "pcs"],
"mode": "snapshot",
"keywords": ["software", "digital"],
"cpvPrefixes": ["72"],
"nations": ["Scotland"],
"maxItems": 100
}

Omitting dates selects yesterday and today in UTC. Dates are inclusive calendar days. FTS is queried by update time, CF by publication time; PCS requests months covering the window and filters release dates locally. Filters are combined with AND; each keywords/CPV/nation list offers alternatives within that filter. Inspect RUN_SUMMARY before treating any export as complete.

Sources and coverage

SourceWhat it addsWindow and paginationLicence
Find a TenderAbove-threshold UK procurement, plus Procurement Act 2023 above/below-threshold notices for England, Wales and Northern Ireland since 24 February 2025; Scottish above-threshold noticesupdatedFrom/updatedTo, 100 releases per page, opaque links.next cursorOGL v3.0
Contracts FinderLegacy PCR 2015 notices, now predominantly awards; complements the transition to FTSpublishedFrom/publishedTo, 100 releases per page, links.next cursorOGL v3.0
Public Contracts ScotlandScottish OJEU/FTS forms, site notices and Quick Quote awards; data from November 2016One calendar month × notice type per request; local date filterOGL v3.0

These feeds are not all UK procurement. Northern Ireland below-threshold notices published only on eTendersNI, Sell2Wales legacy-only notices, private tenders and unpublished Quick Quote invitations are not covered. A Welsh reference is preserved when present, but Sell2Wales is not queried. Organisation identifiers are retained when supplied; absence of an identifier is not evidence of an invalid organisation.

Deduplication and notice versions

With dedup: "exact" (default), the latest release for each source, OCID and stage is retained within the run. Sparse updates inherit missing values from the prior release. Planning, tender, award, contract, change and termination remain separate rows. Multiple releases do not necessarily mean multiple opportunities, and several award releases for one OCID/stage become one latest notice.

Scottish matches use (SC Ref:846105) or an ESPD download link ID to associate an FTS release with PCS OCID ocds-r6ebe6-0000846105. The stage must also match. PCS is preferred; alsoPublishedIn retains merged UIDs and crossRefs.ftsIds retains FTS release IDs. Without PCS in sources, the FTS row and Scottish reference remain available. dedupMethod describes the match; exact matches have dedupConfidence: 1. Unmerged rows have confidence null.

fuzzyCrossSource: true optionally merges FTS/CF rows with equal normalised buyer/title, equal non-null value and currency, the same stage, and dates within three days. Confidence is 0.85, an indicative label rather than a calibrated probability. It can make false matches. The default is false. dedup: "off" retains individual releases and disables both match strategies.

CPV codes come from tender classifications, additional classifications and item classifications. Releases with no CPV inherit the latest CPV context for that source/OCID from the run or retained monitor state. No extra per-OCID requests are made. Awards without observed earlier context can still have an empty CPV list.

Inputs

The complete UI schema is .actor/input_schema.json; unknown fields and malformed values are rejected.

InputDefaultBehaviour
sources["fts","cf","pcs"]Nonempty subset of the three official sources
modesnapshotsnapshot or monitor
dateFrom, dateToYesterday, todayISO YYYY-MM-DD, inclusive UTC days; FTS/CF filter updated/published time respectively
pcsNoticeTypes[2,3,102,103,104]Allowed: 1–7, 12–15, 20–25, 101–104. Site types 101 PIN, 102 tender, 103 award, 104 Quick Quote award
keywords[]Any whole word/phrase in title + full sanitised description; case insensitive
keywordsAll[]All specified words/phrases must match
excludeKeywords[]Reject any matching word/phrase; punctuation is treated literally
cpvPrefixes[]Any string prefix, e.g. "72" or "4521"; codes are not converted to numbers
nations[]England, Scotland, Wales, Northern Ireland, derived from buyer ITL/NUTS region
itlPrefixes[]Any buyer region prefix, e.g. UKM, UKI32
buyerContainsUnsetCase-insensitive buyer organisation substring
minValue, maxValueUnsetGBP bounds; non-GBP valued rows fail a numeric bound, with no currency conversion
includeNoValuetrueUnknown-value rows pass value bounds only when true
stages[]planning, tender, award, contract, change, termination, other
belowThresholdOnlyfalseBest-effort: explicit aboveThreshold: false, PCS site types 102/103/104, or a below-threshold statement in method/status metadata
deadlineAfterUnsetRequire a deadline strictly after an ISO date or timezone-qualified timestamp
dedupexactexact or off
fuzzyCrossSourcefalseOptional FTS/CF buyer/title/value/date match
maxItems1000–100,000; zero delivers nothing and makes no source requests
includeDescriptiontrueFalse outputs null; filters and change detection still use full sanitised text
descriptionMaxChars20000–100,000 output characters
monitorStateKeyUK_TENDERS_STATEKey inside the named uk-tenders-monitor key-value store
requestPacingMs10001,000–60,000 ms minimum between request starts per host
maxRetries50–10 retries after the original attempt
proxyConfigurationNone/directOptional Apify or custom HTTP(S) proxy configuration; provider charges may apply

ITL UKC–UKK maps to England, UKL to Wales, UKM to Scotland and UKN to Northern Ireland. Unknown regions remain null. Buyer location can differ from the place of delivery. The below-threshold flag is a discovery heuristic: site forms, sector exceptions, contract dates and statutory thresholds prevent a reliable universal monetary threshold test. It is not a legal classification.

Output

Each dataset row contains the fields below. The overview dataset view displays the main procurement fields. See SAMPLE_OUTPUT.json for a sanitised real API sample; it is historical, not a current opportunity list.

FieldsMeaning
uid, source, ocid, releaseId, noticeUrlSource release identity (FTS:releaseId, etc.) and official notice link
crossRefs, alsoPublishedIn, dedupMethod, dedupConfidencePCS/Welsh references, FTS IDs, merged source/version UIDs and match evidence
stage, tags, noticeType, noticeTypeLabelNormalised lifecycle and raw source type where supplied; unknown type is null
legalBasis, regimeRaw legal basis ID and readable regime label
title, descriptionSanitised text; optional description truncation
cpvCodes, mainProcurementCategory, procurementMethodPublished classifications, with observed CPV backfill where available
buyerName, buyerId, buyerItl, nationOrganisation and buyer-region fields
valueAmount, valueCurrency, awardedValue, suppliersTender value, falling back to award value; sum of comparable award amounts; organisation suppliers {name,id}
publishedAt, tenderDeadline, contractStart, contractEnd, fetchedAtUTC timestamps or null for unavailable dates
belowThreshold, possiblyTruncatedSourceDiscovery heuristic and PCS completeness warning
license, attributionOGL v3.0 attribution retained in every row

Missing optional values are null; missing collections are empty arrays. Zero values are preserved. Mixed-currency awards are not summed. A row can carry both award and contract tags; award takes stage precedence. Cancellation tags map to termination, amendments to change. No raw parties, contact blocks or source response are passed through.

Illustrative output fragment (synthetic):

{
"uid": "PCS:846105",
"source": "PCS",
"ocid": "ocds-r6ebe6-0000846105",
"crossRefs": { "pcsRef": "846105", "walesRef": null, "ftsIds": ["099191-2026"] },
"alsoPublishedIn": ["FTS:099191-2026"],
"dedupMethod": "scRef",
"stage": "tender",
"title": "Software services procurement",
"buyerName": "Example Council",
"nation": "Scotland",
"valueAmount": 120000,
"valueCurrency": "GBP",
"possiblyTruncatedSource": false,
"license": "Open Government Licence v3.0",
"attribution": "Contains public sector information licensed under the Open Government Licence v3.0."
}

Incremental monitor mode

{
"mode": "monitor",
"sources": ["fts", "cf", "pcs"],
"monitorStateKey": "UK_TENDERS_STATE",
"keywords": ["laboratory", "sequencing"],
"maxItems": 500
}

Run serially with the same state key and a fresh default dataset for each run. Named state retains source cursors/high-water marks, sanitised pending notices, CPV context and hashed delivered content versions for 120 days. After each page or PCS shard the cursor and pending data are saved together. The complete source window is prepared before delivery, allowing cross-source deduplication; a throttled scan can therefore finish with no rows yet delivered.

Only new or materially changed matching notices are pushed. Retrieval time, release-ID-only changes, publication timestamp and dedup bookkeeping do not alone create another delivery. Changes to the full sanitised title/description, values, classifications, buyer, suppliers, deadlines or other substantive fields do. Same-stage version identity is source/OCID/stage, or Scottish reference/stage for a verified Scottish match; dedup: "off" instead tracks release UIDs. Previously delivered content versions are retained, so an unchanged version reappearing after another update is suppressed.

After a completed scan, implicit start dates use the source high-water mark with two days of overlap to pick up delayed publications, including gaps between scheduled runs. Explicit dates repeat that requested window and rely on the seen-set. A pending scan always finishes its original window first. Changing sources or filters while work is pending requires resuming the original configuration or choosing a new state key.

Hitting maxItems or the SDK spending limit retains undelivered matching rows for the next run. Exhausted throttling/network retries or the overall time budget save the current cursor and finish successfully with a resume next run message. RUN_SUMMARY records the stop reason, delivery/request/retry/page counts, pending count and all capped PCS shards. ACTOR_TIMEOUT_AT reserves ten seconds for clean storage/shutdown. Off-platform, set that variable explicitly if a time budget is needed.

Use one writer per state key: concurrent runs can race. Dataset push and key-value checkpoint are separate platform operations; a hard kill between them can leave an ambiguous last row. Absolute exactly-once delivery across that failure window cannot be guaranteed by Apify dataset/KV storage. Inspect partial results before recovery. A nonempty default dataset is refused. Deleting state or replaying data older than retention can redeliver rows. A newly available PCS counterpart can constitute a material update to an earlier FTS-only row.

Snapshot runs are independent exports and can bill for the same notice on later runs. A paused snapshot writes CHECKPOINT for inspection; rerun the desired window in fresh storage. Automatic cross-run cursor continuation is provided by monitor mode.

Reliability and known limitations

  • PCS 300-release cap: month × notice-type shards returning at least 300 releases are marked possiblyTruncatedSource, logged, and listed under RUN_SUMMARY.truncatedShards. They are not complete exports. The documented API cannot reliably subdivide a month: day-formatted dateFrom is misparsed, and dateTo/page were ignored in the supplied probe. No invented day/page sharding is attempted. The strategy is isolated in pcsShards() for future changes.
  • The cloud Actor's default run timeout is 900 seconds (PCS shards can take 6–60 s each). Raise it for long historical windows.
  • For Contracts Finder rows, valueAmount is only the advertised tender value; when CF omits it the field is null (award totals, often a placeholder 0, stay in awardedValue).
  • PCS is slow and uses text/json. Requests have a 60-second timeout. Its missing TLS intermediate is bundled from Sectigo and trusted only for the PCS API host, alongside Node's normal roots. Certificate and hostname verification remain enabled. The certificate is never fetched at runtime.
  • FTS can throttle despite successful short probes. Request starts are paced by at least one second per host. HTTP 429/503 honour Retry-After seconds or HTTP dates. CF HTTP 403 is treated as throttling with at least five minutes of backoff. Other 5xx/network failures use exponential backoff with jitter. The cursor never advances on a failed attempt.
  • Invalid JSON/envelopes, unsafe pagination URLs, cursor cycles, other rejected responses and bodies exceeding 20 MiB fail clearly. No login or access-control workaround is attempted. Normal retries stop cleanly if the requested wait cannot fit the remaining time.
  • Source windows are not transactional, publisher updates may arrive late, and CF contains legacy notices. Full UK procurement coverage is not promised. maxItems limits delivery, not the number scanned: deduplication requires preparing the whole window. Large historical windows consume memory/checkpoint space; use small windows and the 256 MB default (maximum 1024 MB), and measure before increasing coverage.
  • Missing CPV, buyer geography or declared value can make a filter exclude a real opportunity. Award values and tender estimates are not equivalent. No exchange rates, statutory threshold calculations or tender suitability scoring are performed.

Personal-data policy

There is no opt-in for personal contact data in v1. The output is an organisation-level discovery feed. ContactPoint names, emails, telephone/fax numbers and personal contact URLs are omitted. Contact names found in those blocks and identifiable individual-party names are removed from text; emails and telephone-like strings are redacted. Parties marked as natural persons, individuals or sole traders are excluded from supplier names. Organisation names and published organisation identifiers remain. Official notice links remain so users can consult the publisher under its terms.

Unstructured prose can contain personal information the publisher has not labelled; automated redaction is best-effort, not a complete person-name recogniser. Do not treat this feed as a contact list. Raw source documents are not retained by the Actor. Test fixtures use synthetic contacts; the real sample is sanitised before writing.

Pricing

Pay per event: $0.005 per delivered notice ($5 per 1,000) plus $0.005 per run start (Apify counts one start event per GB of run memory, minimum one; the default 256–512 MB is one event). Only notices saved to the dataset are charged. A run that finds nothing costs just the $0.005 start fee. Example: a daily run delivering 40 new notices costs 40 × $0.005 + $0.005 = $0.205.

Monitor mode charges only new notices. In mode: "monitor" the Actor remembers every notice version it has already delivered (in the uk-tenders-monitor key-value store under your monitorStateKey). Later runs skip those versions without pushing them, so you are not charged again for notices you have already received; only new notices, or notices whose material content has changed, are delivered and billed. Scheduled monitor runs still pay the $0.005 start fee each time.

Notices that do not match your filters are never pushed and never charged. maxItems caps the number of billed notices per run, and if you set a maximum cost per run in Apify the Actor stops cleanly before exceeding it (a run stopped by the limit keeps the notices already delivered). Apify platform usage is included in these prices.

Local development and acceptance

Use Node 22:

npm ci --cache .npm-cache
npm test
npm run check
npm run validate
npm run smoke -- live
npm run smoke -- empty
npm run smoke -- budget
npm run smoke -- zero-limit
npm run smoke -- zero-budget
npm run smoke -- invalid-input
npm run smoke -- monitor-twice

In this workspace, prepend the supplied Node path if needed:

export PATH="$PWD/../.tools/node-v22.23.4-darwin-arm64/bin:$PATH"

The cache is inside this Actor folder to respect the task's write boundary. Unit tests use injected HTTP and make no network calls. Non-live smoke modes use synthetic fixtures with the real local SDK, storage and billing simulation. Live smoke gently queries the historical 20 October 2026 window: FTS + CF + one PCS month/type, max 20 delivered rows and at most 20 source attempts. It refreshes SAMPLE_OUTPUT.json. Smoke subprocesses use an environment allowlist without account tokens/cloud identity. Reports are saved in research/smoke-*.json; monitor-twice uses fresh datasets and shared named state and asserts the second dataset is empty.

The budget smoke uses the SDK's synthetic $1/item local test event and a $2 cap; it verifies two automatic item events and spends no money. The additional zero-budget smoke exercises the real main entrypoint with an explicit off-platform $0 cap and asserts no source requests. Those synthetic prices are not the proposed production prices. Restricted local hosts can set CRAWLEE_LOCAL_PROCESS_METRICS=true for process-only metrics; cloud runs keep standard platform metrics. Put manual input in storage/key_value_stores/default/INPUT.json and run npm start. Leave APIFY_IS_AT_HOME unset locally (the pinned SDK treats any nonempty string, including false, as cloud mode).

The Dockerfile uses apify/actor-node:22, a lockfile and npm ci --omit=dev. No publishing/login command is part of this repository's scripts. STATUS.md records acceptance and the owner-approved steps still needed before any deployment.

FAQ

Can I call the APIs myself? Yes. They are public and keyless. This Actor adds a common output, Scottish matching, local filters and persistent monitoring.

Why fewer results than requested? Filters, missing classifications, seen versions, a spending limit, PCS truncation or an unfinished source scan can reduce output. Read RUN_SUMMARY, particularly stopReason, resumeNextRun and truncatedShards.

Does monitoring re-charge old notices? Previously delivered content versions within retained state are suppressed. Material updates are new results. Start events are separate; deletion/expiry of state and hard-kill recovery have the limitations described above.

Does a notice imply I can still bid? No. Awards, planning and cancelled processes are included by default. Filter stages and deadlineAfter, and verify the current official notice and documents.

Contains public sector information licensed under the Open Government Licence v3.0. Sources: Cabinet Office Find a Tender and Contracts Finder, and Scottish Government Public Contracts Scotland. Every row retains that licence label and attribution. The licence does not grant rights to personal data, third-party content or official logos beyond its terms.

This independent tool is not endorsed by those publishers. Data is provisional, may be incomplete or delayed, and is supplied without a completeness guarantee. This is not legal, procurement or bidding advice. Consult the official notice and applicable terms before relying on or redistributing information.