UK and Ireland tender data API
Live tenders collected from buyers' own portals, not counted from national notices, and contracts due back on the market. Read-only JSON, one key, and a free demo to start.
Data that free feeds do not have
Find a Tender and Contracts Finder publish open data, and plenty of tools repackage it. Around one in four live tenders is not on any national portal: it is published only on the buyer's own procurement portal. TenderSignal collects those tenders alongside the national notices, and the API gives you both in one feed, with a hard_to_find flag on every tender that is not on the national portals.
What you can build
- Bring new tenders in your sectors into your CRM or bid tracker, and tell the right person on your team.
- Follow the buyers you sell to, with their live and past notices and, on API Pro, their procurement contact.
- See contracts due back on the market, with the month we expect each to return, and plan your pipeline months ahead.
- Pull award notices to see who won what, for how much, and when each contract ends.
Simple to use
The API is read-only JSON over HTTPS with one key in the Authorization header. Lists are paged with cursors that also work for polling: keep the last cursor you received and pass it next time to get only what is new. Allowances count records, not calls, and a record you have already received this month is free, so polling for new tenders costs nothing extra.
Every response tells you your plan, your allowance and what you have used, in its headers, so your integration can keep an eye on its own usage. Errors come back as JSON with a short code and a plain explanation.
Start free
Every verified TenderSignal account can create a demo key with a one-off allowance. Try real requests against live data, then choose API Starter or API Pro when you are ready. There are no sales calls and no demos to book: sign up, create a key and start. If you need more than API Pro includes, email [email protected] and we will set up a larger allowance.
Plans
API Starter
- 2,500 records a month
- Tenders, awards and buyers
- Buyer contacts on tenders also on the national portals, for accounts billed in the UK, the EEA or a country with UK adequacy
- Up to 5 keys
API Pro
- 10,000 records a month
- Everything in API Starter, plus renewals
- Buyer contacts on every tender, including hard-to-find ones, for accounts billed in the UK, the EEA or a country with UK adequacy
- Links to buyers' portals, up to 2,000 records a month
- Up to 5 keys
Buyer contact details are included for accounts billed in the UK, the EEA or a country with UK adequacy.
Need more than 10,000 records a month? Email [email protected]. API plans are separate from the website plans and are billed monthly; cancel any time from your billing page.
Your keys
Quick start
Keep your key in an environment variable and send it in the Authorization header. Each example asks for five live tenders that are not on the national portals.
curl -H "Authorization: Bearer $TENDERSIGNAL_API_KEY" \
"https://tendersignal.co.uk/api/v1/tenders?hard_to_find=true&limit=5"const res = await fetch("https://tendersignal.co.uk/api/v1/tenders?hard_to_find=true&limit=5", {
headers: { Authorization: `Bearer ${process.env.TENDERSIGNAL_API_KEY}` },
});
const { data, next_cursor } = await res.json();import os, requests
r = requests.get(
"https://tendersignal.co.uk/api/v1/tenders",
params={"hard_to_find": "true", "limit": 5},
headers={"Authorization": f"Bearer {os.environ['TENDERSIGNAL_API_KEY']}"},
)
data = r.json()["data"]Use it from your AI assistant
The same data is available to AI assistants through our MCP server, so you can ask Claude, Cursor or another MCP client for tenders, awards, buyers and renewals in plain English. It uses the same API key, the same plan and the same record allowance as the API: a record your assistant fetches counts once, exactly as it would over the API.
Server address https://www.tendersignal.co.uk/mcp. Send your key in the Authorization header. Assistants that only connect through a sign-in button, such as the connector screens in claude.ai and ChatGPT, are not supported yet.
claude mcp add --transport http tendersignal https://www.tendersignal.co.uk/mcp --header "Authorization: Bearer $TENDERSIGNAL_API_KEY"{
"mcpServers": {
"tendersignal": {
"url": "https://www.tendersignal.co.uk/mcp",
"headers": {
"Authorization": "Bearer ts_live_your_key"
}
}
}
}{
"mcpServers": {
"tendersignal": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://www.tendersignal.co.uk/mcp",
"--header",
"Authorization:${TENDERSIGNAL_AUTH}"
],
"env": {
"TENDERSIGNAL_AUTH": "Bearer ts_live_your_key"
}
}
}
}Tools
search_tenders: Search tenders with the same filters as /tenders, including hard_to_find. (Every plan)get_tender: One tender by id. (Every plan)search_awards: Search award notices with the same filters as /awards. (Every plan)list_renewals: Contracts expected to be re-tendered, as /renewals. (API Pro)search_buyers: Find buyers and their slugs, as /buyers. (API Starter and API Pro)get_buyer: One buyer by slug. (API Starter and API Pro)get_usage: Your plan, allowance and usage. Free. (Every plan)
Fields by plan
Every record carries the fields marked for your plan. Buyer contact details are included for accounts billed in the UK, the EEA or a country with UK adequacy. Where details are withheld the field is absent and the response says why.
tenders
| Field | Plans | What it is |
|---|---|---|
| id | Every plan | TenderSignal id, the number in the tender's page address. |
| url | Every plan | The tender's page on tendersignal.co.uk. |
| title | Every plan | Notice title. |
| description | Every plan | Full description. Links to buyers' portals are removed unless your plan includes them. |
| status | Every plan | live, closed or cancelled. |
| notice_type | Every plan | tender, amendment or pin (an early market notice). |
| buyer | Every plan | The buying organisation: name, slug, type, type_group and website. |
| contract_type | Every plan | works, services, supplies or null. |
| procedure_type | Every plan | The procurement procedure as published. |
| cpv_codes | Every plan | CPV codes on the notice. |
| sectors | Every plan | TenderSignal sector slugs, the same as the sector parameter. |
| region | Every plan | Region as published. |
| nation | Every plan | england, scotland, wales, northern-ireland or ireland. |
| country | Every plan | UK, GB, GI or IE. |
| value | Every plan | min, max and currency, in pounds or euros, or null when no value was published. |
| published_at | Every plan | When the notice was published, ISO 8601 in UTC. |
| deadline | Every plan | Response deadline, ISO 8601 in UTC. |
| enquiry_deadline | Every plan | Deadline for clarification questions, when published. |
| contract_start_date | Every plan | YYYY-MM-DD. |
| contract_end_date | Every plan | YYYY-MM-DD. |
| duration_months | Every plan | Contract length in months. |
| is_framework | Every plan | true for a framework agreement. |
| is_dps | Every plan | true for a dynamic purchasing system. |
| hard_to_find | Every plan | true: not on the national portals (we found it on the buyer's own portal); false: also on a national portal; null: not yet checked. |
| contact | Every plan on tenders also on the national portals; API Pro on every tender. Only for accounts whose billing address is in the UK, the EEA or a country the UK recognises as adequate; otherwise absent, with contacts_withheld_reason in the response. | The buyer's contact: name, email and phone. Absent when your plan does not include it for this tender. Contact details are returned only to accounts whose billing address is in the UK, the EEA or a country the UK recognises as adequate for data protection. Otherwise the field is absent and the response carries contacts_withheld_reason. |
| source_url | API Pro | The notice on the buyer's portal. |
| submission_url | API Pro | Where to respond. |
| portal_link_capped | API Pro | Present and true when this month's portal-link limit was reached, so the links were left out. |
awards
| Field | Plans | What it is |
|---|---|---|
| id | Every plan | TenderSignal id of the award notice. |
| url | Every plan | The award's page on tendersignal.co.uk. |
| title | Every plan | Notice title. |
| buyer | Every plan | The buying organisation: name, slug, type, type_group and website. |
| cpv_codes | Every plan | CPV codes on the notice. |
| sectors | Every plan | TenderSignal sector slugs, the same as the sector parameter. |
| region | Every plan | Region as published. |
| nation | Every plan | england, scotland, wales, northern-ireland or ireland. |
| country | Every plan | UK, GB, GI or IE. |
| suppliers | Every plan | The winning suppliers, as a list. |
| award_value | Every plan | amount and currency, or null. |
| award_date | Every plan | YYYY-MM-DD. |
| published_at | Every plan | When the award notice was published, ISO 8601 in UTC. |
| contract_start_date | Every plan | YYYY-MM-DD. |
| contract_end_date | Every plan | YYYY-MM-DD. |
| duration_months | Every plan | Contract length in months. |
| source_url | API Pro | The notice on the buyer's portal. |
| portal_link_capped | API Pro | Present and true when this month's portal-link limit was reached, so the links were left out. |
renewals
| Field | Plans | What it is |
|---|---|---|
| id | API Pro | TenderSignal id of the renewal. |
| title | API Pro | The current contract's title. |
| description | API Pro | The current contract's description. |
| buyer | API Pro | The buying organisation. |
| incumbent | API Pro | The suppliers that hold the contract now, as a list. |
| contract_end_date | API Pro | When the current contract ends, YYYY-MM-DD. |
| expected_retender_month | API Pro | The month we expect it back on the market, YYYY-MM. |
| value | API Pro | min, max and currency of the current contract, or null. |
| cpv_codes | API Pro | CPV codes of the current contract. |
| sectors | API Pro | TenderSignal sector slugs. |
| region | API Pro | Region as published. |
| original_award | API Pro | id and url of the award notice for the current contract. |
| retendered_as | API Pro | id and url of the new tender once it is published, otherwise null. |
| contact | API Pro | The buyer's contact: name, email and phone. Contact details are returned only to accounts whose billing address is in the UK, the EEA or a country the UK recognises as adequate for data protection. Otherwise the field is absent and the response carries contacts_withheld_reason. |
| source_url | API Pro | The award on the buyer's portal. |
| portal_link_capped | API Pro | Present and true when this month's portal-link limit was reached, so the links were left out. |
buyers
| Field | Plans | What it is |
|---|---|---|
| slug | Every plan | Use it with the buyer parameter and /buyers/:slug. |
| name | Every plan | Buyer name. |
| type | Every plan | Buyer type, for example local-council or nhs. |
| type_group | Every plan | The buyer_type group the type belongs to. |
| nation | Every plan | england, scotland, wales, northern-ireland or ireland. |
| tender_count | Every plan | Notices from this buyer. |
| live_count | Every plan | Live tenders from this buyer now. |
| url | Every plan | The buyer's page on tendersignal.co.uk. |
| procurement_contact | API Pro | The buyer's procurement email and phone, when known. Contact details are returned only to accounts whose billing address is in the UK, the EEA or a country the UK recognises as adequate for data protection. Otherwise the field is absent and the response carries contacts_withheld_reason. |
Endpoints and parameters
Base address https://tendersignal.co.uk/api/v1. Every endpoint is a GET that returns JSON. Unknown parameters are refused with a 400 that names them.
GET /usage
Your plan, allowance, usage, what your plan includes and the terms version you accepted. Free. contacts is all, national_portal_tenders or "none"; when it is "none", contacts_withheld_reason says billing_country_unknown or billing_country_not_eligible. (Every plan)
GET /tenders
Tenders in the UK and Ireland, live by default, oldest id first. (Every plan)
status: live (default), closed or all.notice_type: tender, amendment or pin. PINs (early market notices) only appear when you ask for them.q: Words in the title or description. Separate phrases with commas to match any of them.sector: Comma list of sector slugs, for example construction,it-software. Every slug is listed under Sector slugs below.cpv: Comma list of CPV codes. 45000000 matches every code that starts 45.region: Comma list from: london, south-east, south-west, east-of-england, east-midlands, west-midlands, yorkshire, north-west, north-east, wales, scotland, northern-ireland, ireland. uk-wide is not accepted: leave region out for no region filter. ireland adds Irish tenders; use nation=ireland for Ireland only.buyer: A buyer slug from /buyers.buyer_name: Part of the buyer's name.buyer_type: Comma list: local-council, nhs, central-gov, housing-association, university, education, emergency-services, utility, public-body.value_min: Minimum value in the notice's own currency, for example 25000.value_max: Maximum value in the notice's own currency.limit: Records per page, 1 to 100. Default 20.cursor: next_cursor or resume_cursor from an earlier response.nation: Comma list: england, scotland, wales, northern-ireland, ireland.closing_after: Deadline on or after this date or time. A date alone means midnight UK time.closing_before: Deadline before this date or time.published_since: Published on or after this date or time.hard_to_find: hard_to_find=true returns only tenders not on the national portals; hard_to_find=false returns every other tender, including ones not yet checked.
GET /tenders/:id
One tender by id. A merged record answers 404 with canonical_id. (Every plan)
GET /awards
Award notices: who won, for how much and when. (Every plan)
q: Words in the title or description. Separate phrases with commas to match any of them.sector: Comma list of sector slugs, for example construction,it-software. Every slug is listed under Sector slugs below.cpv: Comma list of CPV codes. 45000000 matches every code that starts 45.region: Comma list from: london, south-east, south-west, east-of-england, east-midlands, west-midlands, yorkshire, north-west, north-east, wales, scotland, northern-ireland, ireland. uk-wide is not accepted: leave region out for no region filter. ireland adds Irish tenders; use nation=ireland for Ireland only.buyer: A buyer slug from /buyers.buyer_name: Part of the buyer's name.buyer_type: Comma list: local-council, nhs, central-gov, housing-association, university, education, emergency-services, utility, public-body.value_min: Minimum value in the notice's own currency, for example 25000.value_max: Maximum value in the notice's own currency.limit: Records per page, 1 to 100. Default 20.cursor: next_cursor or resume_cursor from an earlier response.nation: Comma list: england, scotland, wales, northern-ireland, ireland.supplier: Part of a winning supplier's name.awarded_since: Awarded on or after this date.awarded_before: Awarded before this date.published_since: Published on or after this date or time.
GET /buyers
UK and Irish buyers, by slug. (API Starter and API Pro)
q: Part of the buyer's name.buyer_type: Comma list of buyer type groups, as on /tenders.nation: Comma list: england, scotland, wales, northern-ireland, ireland.has_live: true for buyers with live tenders now.limit: Records per page, 1 to 100. Default 20.cursor: next_cursor or resume_cursor from an earlier response.
GET /buyers/:slug
One buyer by slug. (API Starter and API Pro)
GET /renewals
Contracts due back on the market, with the month we expect each to return. (API Pro)
q: Words in the title.sector: Comma list of sector slugs, for example construction,it-software. Every slug is listed under Sector slugs below.cpv: Comma list of CPV codes. 45000000 matches every code that starts 45.region: Comma list from: london, south-east, south-west, east-of-england, east-midlands, west-midlands, yorkshire, north-west, north-east, wales, scotland, northern-ireland, ireland. uk-wide is not accepted: leave region out for no region filter. ireland adds Irish tenders; use nation=ireland for Ireland only.buyer: A buyer slug from /buyers.buyer_name: Part of the buyer's name.buyer_type: Comma list: local-council, nhs, central-gov, housing-association, university, education, emergency-services, utility, public-body.value_min: Minimum value in the notice's own currency, for example 25000.value_max: Maximum value in the notice's own currency.limit: Records per page, 1 to 100. Default 20.cursor: next_cursor or resume_cursor from an earlier response.incumbent: Part of the current supplier's name.retender_from: Expected back on the market in or after this month, YYYY-MM.retender_to: Expected back on the market in or before this month, YYYY-MM.
Sector slugs
Use these slugs with the sector parameter, for example sector=construction,it-software. Each sector covers a set of CPV codes; use cpv instead for a narrower match.
construction: Construction & Civil Engineeringit-software: IT & Softwaredata-digital: Data & Digitalhealthcare: Healthcare & Medicalsocial-care: Social Carefacilities-property: Facilities & Property Managementprofessional-services: Professional Services & Consultingengineering-manufacturing: Engineering & Manufacturingenvironmental-utilities: Environmental & Utilitiesenergy: Energytransport-logistics: Transport & Logisticssecurity-services: Security Serviceseducation-training: Education & Trainingmarketing-communications: Marketing & Communicationslegal-financial: Legal & Financial Servicesgoods-supplies: Goods & Suppliescultural-recreation: Cultural & Recreation
Records, limits and errors
Allowances count records: each tender, award, buyer or renewal in a response. A record you have already received this month is free, and /usage and errors cost nothing. Paid plans reset on the 1st of each month (UTC); the demo allowance is a one-off.
If a page would go past your allowance you get the records that fit and a cursor to carry on later. Each key may make 60 requests a minute. On API Pro, records past the monthly portal-link limit arrive without their portal links and carry portal_link_capped.
Every response carries these headers:
X-Api-Plan: starter
X-Records-Limit: 2500
X-Records-Used: 340
X-Records-Remaining: 2160
X-Records-Charged: 20
X-Records-Reset: 2026-11-01T00:00:00.000Z
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-Portal-Links-Limit: 2000
X-Portal-Links-Used: 120
X-Portal-Links-Withheld: 0
Cache-Control: no-store| 400 | invalid_parameter | An unknown parameter, a bad value, an id that is too large or a cursor from another endpoint. The response names the parameter. |
| 401 | invalid_key | A missing, malformed, unknown or revoked key, or a key sent in the URL. |
| 403 | plan_required | The endpoint is not in your plan. The response includes upgrade_url. |
| 403 | suspended | The account or its API access is suspended. |
| 404 | not_found | No such record or endpoint. |
| 404 | merged | The record was merged into another one. The response includes canonical_id. |
| 405 | method_not_allowed | Any method other than GET, HEAD included. The API is read-only. Nothing is charged. |
| 429 | rate_limited | More than 60 requests a minute on one key. Wait for the Retry-After header. |
| 429 | records_exhausted | Your allowance is used. The response says how much you used and when it resets. |
| 503 | query_timeout | The query took too long. Add a filter, such as a date or a sector. Nothing is charged. |
| 500 | server_error | Something went wrong on our side. Try again, and email [email protected] if it persists. |
When your allowance is used, the API answers 429:
{
"error": "Your record allowance for this month has been used.",
"code": "records_exhausted",
"plan": "starter",
"allowance": 2500,
"used": 2500,
"remaining": 0,
"resets": "2026-11-01T00:00:00.000Z",
"upgrade_url": "https://tendersignal.co.uk/developers#pricing",
"attribution": "Contains public sector information licensed under the Open Government Licence v3.0 ..."
}Pagination, polling and the response envelope
Lists come oldest id first, up to 100 records a page. Pass next_cursor as cursor to get the next page; it is null when there is nothing more right now.
To poll for new records, store resume_cursor from your last response and pass it as cursor next time. You get only records added since. If nothing is new, data is empty and resume_cursor is the cursor you sent, so keep using it. Records you already have this month cost nothing, so polling every few minutes is fine.
Next to data (or error) every JSON response carries these top-level fields.
| Field | Plans | What it is |
|---|---|---|
| attribution | Every plan | The attribution statement for the public sector information in the data. In every JSON response, errors included. Include it wherever you show records outside your own systems. |
| contacts_withheld_reason | Every plan | Present on data responses only when contact details are withheld for your billing country: billing_country_unknown (no billing country on your account) or billing_country_not_eligible (outside the UK, the EEA and the countries the UK recognises as adequate). On /usage it sits inside data. |
Using the data
- Use the data for your own internal business purposes: your CRM, reports, analysis, bid process and internal tools.
- You may share individual records with your own clients or advisers where it is incidental to your service to them, at most fifty records per recipient per month, and never as a feed or a tool your clients can search themselves.
- Do not resell, sublicense, publish or make the data publicly available.
- Do not use the data to build a competing product or service, or anything that makes tenders, awards, buyer information or renewal predictions available to others.
- AI: you may use AI tools on the data for your own internal use, but do not train or fine tune models that are used for others, and do not put the data into any third party AI service that keeps it or trains on it.
- Do not use the API or the data to map where or how we collect our information.
- Keep the attribution statement, which is in every response, wherever you show records outside your own systems.
- Use buyer contact details only to contact the buyer about the opportunity they relate to. You are an independent controller of the contact details you receive and responsible for complying with data protection law.
- Within 30 days after your plan ends, delete the data, apart from the exceptions in clause 15.2 of the terms.
The full terms are at API Terms. The attribution statement:
Contains public sector information licensed under the Open Government Licence v3.0 (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Contains Irish public sector data from the Office of Government Procurement licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) licence (https://creativecommons.org/licenses/by/4.0/). This information has been modified and combined with other information by TenderSignal.