# UK public-tender API — every contract opportunity and award published by a UK public body on Contracts Finder (central government, NHS, councils, universities) in clean JSON: full notice text, response deadline, contract value, winning supplier, contract start/end dates, CPV codes and the buyer's published contact. No api_key.

> Search UK public-sector contract notices by phrase, status, value, deadline, CPV code and publication date. Every hit already carries the FULL notice text (no second call), plus the money: the published value range for live tenders, and the winning supplier, the awarded amount and the contract end date for awards.
> ReefAPI engine `uk-tenders` · 2 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/uk-tenders/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /uk-tenders/v1/search — 1 credit
Search UK public-sector contract notices by phrase, status, value, deadline, CPV code and publication date. Every hit already carries the FULL notice text (no second call), plus the money: the published value range for live tenders, and the winning supplier, the awarded amount and the contract end date for awards.

**Parameters:**
- `q` (string, required) — What to search for across the notice title and full description. By default this is treated as an EXACT PHRASE — the engine quotes it for you, because the raw index otherwise matches single words and returns thousands of irrelevant notices (measured: 'web scraping' unquoted = 7,802 hits, quoted = 12). Set `phrase=false` for the loose behaviour.
- `phrase` (boolean, optional, default true) — true (default): match `q` as an exact phrase. false: let the index match the words loosely — much broader and much noisier. What was actually sent upstream comes back as `query_sent`.
- `statuses` (array, optional) — Restrict to these notice statuses (comma-separated string or list). Empty = all. Use 'Open' for things you can still bid on and 'Awarded' to see who won and for how much. ⚠️ An unknown value silently returns zero results upstream, so this engine rejects unknown values instead. [one of: Open, Closed, Awarded, Cancelled, Unsuccessful]
- `notice_types` (array, optional) — Restrict to these notice types (comma-separated string or list). 'Contract' is a live procurement; 'Pipeline' is an early warning about one that is coming. [one of: Contract, Pipeline, Pre-procurement, Future opportunity]
- `published_from` (string, optional) — Only notices published on or after this date (YYYY-MM-DD). This one runs UPSTREAM and bites hard — measured 86 → 8 on the same query — so it is the cheapest way to keep a search fresh.
- `published_to` (string, optional) — Only notices published on or before this date (YYYY-MM-DD).
- `published_within_days` (integer, optional) — Convenience for `published_from`: only notices published in the last N days. Translated into the upstream date filter, so it is genuinely cheap. If you also pass `published_from`, that wins.
- `deadline_from` (string, optional) — Only notices whose response deadline falls on or after this date (YYYY-MM-DD) — i.e. ones there is still time to answer. Runs upstream (measured 86 → 6).
- `min_value` (number, optional) — Only notices whose published contract value is at least this many GBP. Notices that publish no value at all are dropped by this filter — leave it out if you would rather see them.
- `cpv_codes` (array, optional) — EU Common Procurement Vocabulary codes to restrict to (comma-separated string or list). 72000000 = IT services, 48000000 = software packages, 79000000 = business services. Useful for sweeping a whole category without a keyword.
- `sort` (enum, optional, default "newest") — Row order. Applied locally, because the API ignores its own `sort` field. [one of: newest, deadline, value, relevance]
- `limit` (integer, optional, default 25) — How many notices to return (1–500, default 25). ⚠️ The API has no paging of any kind (every offset/page parameter was tested and ignored), so this is also the depth ceiling: if `total_matches` is larger than what you asked for, narrow the query instead of paging.

**Returns:** notices[]{id, url, notice_identifier, title, description, buyer, notice_type, status, published_at, deadline, contract_start, contract_end, value_low, value_high, value_currency, awarded_value, awarded_supplier, awarded_at, cpv_codes[], cpv_description, region, postcode, suitable_for_sme}, total_matches, returned, query_sent, truncated, filtered_out

**Example request body:**
```json
{
  "q": "web scraping",
  "limit": 10
}
```

### POST /uk-tenders/v1/notice — 1 credit
One notice in full by id: the buyer's published contact details (name, e-mail, phone, address), the 'how to respond' instructions with the portal link, the procedure type, the number of times the notice has been viewed (a competition signal), and the complete award block — every winning supplier with their address, the amount and the contract start and end dates. None of this is in the search response.

**Parameters:**
- `id` (string, required) — The Contracts Finder notice UUID, as returned by `search` in `id`. A full notice URL also works — the id is read out of it.

**Returns:** notice{id, url, notice_identifier, title, description, buyer, notice_type, status, published_at, deadline, contract_start, contract_end, value_low, value_high, awarded_value, awarded_supplier, awarded_at, awards[]{supplier,supplier_address,value,awarded_at,contract_start,contract_end,procedure_type,duns_number}, cpv_codes[], cpv_description, region, nationwide, coordinates{lat,lon}, sector, procedure_type, contract_kind, is_framework_agreement, is_extension_possible, additional_text, view_count, version, is_pre_awarded, created_at, last_updated, contact{name,email,phone,address,town,postcode,country,website}}

**Example request body:**
```json
{
  "id": "ec641d32-1f15-48f3-9458-bc4cd94b04c5"
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=uk-tenders
- Human docs page: https://reefapi.com/docs/uk-tenders
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
