# ukintel.uk > Pay-per-call UK intelligence for AI agents, as clean JSON. Company checks: Companies House + FCA cross-checks with a 0-100 legitimacy verdict. Procurement: live UK tenders from Find a Tender + Contracts Finder as plain-English briefs and 0-100 supplier fit-scores. Grants: live GOV.UK funding calls matched to a project profile with ELIGIBLE/UNCERTAIN/INELIGIBLE verdicts, plus funder giving-history from the 360Giving open-data corpus. No signup, no API key. Pay per call in USDC over the x402 protocol (HTTP 402). No account, no API key, no rate-limit negotiation: call the endpoint, get a 402 with payment terms, pay, retry. That is the whole integration. Base URL: https://api.ukintel.uk Payment network: eip155:8453 (Base mainnet) Asset: USDC · Pay to: 0x8aa6a85a2723e2816204f3cf48d76b84bafdaab4 Machine docs: https://api.ukintel.uk/openapi.json · https://api.ukintel.uk/.well-known/x402 ## Why an agent would pay for this The underlying registers are free but awkward. Companies House and the FCA register need accounts you cannot create mid-task, and turning raw filings into a judgement costs thousands of tokens per company. UK tenders live on two differently-shaped portals (Find a Tender has no keyword search at all) full of procurement jargon. UK grants are worse: GOV.UK Find a Grant has NO API of any kind, and funder giving-history is scattered across hundreds of separately-published open-data files. This service returns the judgement already made - a risk verdict, a tender brief, a fit-score, a grant eligibility verdict, a funder dossier - in about 800 tokens, with every rule that fired named so you can audit or override it. ## The response envelope - identical on every endpoint ```json { "query": { ...echo of what was asked... }, "result": { ...the endpoint payload... }, "verdict": { "score": 0-100 | null, "band": "low_risk|caution|high_risk" | null, "flags": [ { "code": "...", "detail": "..." } ], "narrative": "<= 2 sentences, may be null" }, "confidence": "high | medium | low", "as_of": "ISO-8601 - when WE fetched the underlying data, not when you asked", "sources": [ { "name": "Companies House", "fetched": "ISO-8601", "url": "..." } ], "attribution": "Open Government Licence v3.0 ...", "notice": "Information, not advice.", "cost": { "amount": "0.10", "currency": "USDC" } } ``` Guarantees: deterministic key order · explicit nulls, never missing keys · no HTML anywhere · about 800 tokens by default, `?detail=full` lifts the cap · `as_of` is our fetch time, never your request time. `confidence` is high when every source was fetched fresh or served from cache within its window; medium when a source was stale; low when a source failed and we answered from cache - and then the failure is named in `flags`. We serve slightly old data rather than a 500. ## Paid endpoints ### GET /v1/company/search — $0.005 Find a UK company by name. Returns the top 5 matches from the Companies House register with number, name, status and incorporation date. Taster tier - cheap enough to try on a whim before paying for a full profile or verdict. Returns: results[] of { company_number, name, status, incorporated, address_snippet }, plus total_matches. Parameters: - `q` (query, required) — Company name or fragment to search for. - `limit` (query, optional) — Number of matches to return, 1-5. Defaults to 5. ### GET /v1/company/{number} — $0.02 One UK company as clean structured JSON: status, incorporation date, company type, SIC codes, registered office, accounts and confirmation-statement due dates with overdue booleans, and officer counts. Sourced live from Companies House. Returns: result = { name, company_number, status, type, incorporated, registered_office, sic_codes[], accounts{}, confirmation_statement{}, officers{ active, total, resigned_last_12m }, age_years }. Parameters: - `number` (path, required) — UK company number. 8 characters; two-letter prefixes are supported (SC = Scotland, NI = Northern Ireland, OC = LLP). - `detail` (query, optional) — Set to 'full' to add filing history (last 10) and anonymised officer records, and to lift the ~800 token response cap. ### GET /v1/company/{number}/verdict — $0.10 Should an agent trust this UK company? Returns a 0-100 verdict and low_risk/caution/high_risk band, with every rule that fired named in the response and the register value that triggered it: STATUS_DISSOLVED, STRIKE_OFF_ACTIVE, ACCOUNTS_OVERDUE, NO_ACTIVE_DIRECTORS, OFFICER_CHURN, FS_SIC_NOT_FCA and 9 more. Rules are deterministic and published, so you can audit the verdict or re-weight it. Never model-scored. Returns: Everything the profile returns, plus verdict = { score 0-100, band low_risk|caution|high_risk, flags[{code,detail}], fca{}, narrative }. Parameters: - `number` (path, required) — UK company number. 8 characters; two-letter prefixes are supported (SC = Scotland, NI = Northern Ireland, OC = LLP). - `detail` (query, optional) — Set to 'full' to add filing history (last 10) and anonymised officer records, and to lift the ~800 token response cap. ### GET /v1/company/{number}/fca — $0.02 Is this UK company regulated by the Financial Conduct Authority? Returns register status, a permissions summary and any warnings - sold separately from the full verdict because fintech-vetting agents often want only this. Returns: result.fca = { checked, regulated, frn, firm_name, status, permissions_summary, warnings[], note }. When the register is unavailable, checked=false and the reason is named - never a 500. Parameters: - `number` (path, required) — UK company number. 8 characters; two-letter prefixes are supported (SC = Scotland, NI = Northern Ireland, OC = LLP). ### GET /v1/tenders/search — $0.05 Live UK public-sector tenders from Find a Tender and Contracts Finder in one call. Returns the top 10 matching notices as one-paragraph plain-English briefs with buyer, value, deadline, CPV codes (honest null when the notice carries none) and the official notice link. Searches a 6-hourly refreshed index - no signup with either portal needed. Returns: result = { total_matched, returned, notices[] of { ocid, title, buyer, value, stage, published, deadline, days_remaining, region, cpv, summary, source{name, notice_url} }, excluded{} } - excluded{} reports notices honest-nulled out by cpv/region/value/deadline filters. Parameters: - `q` (query, optional) — Keywords, synonym-expanded (e.g. 'cleaning' also finds janitorial and hygiene services). At least one of q, cpv or region is required. - `cpv` (query, optional) — CPV code prefix filter, comma-separated (e.g. 909,45233). Notices without CPV codes are excluded and counted. - `region` (query, optional) — UK nation or English region: scotland, wales, northern-ireland, london, north-east, north-west, yorkshire, east-midlands, west-midlands, east-of-england, south-east, south-west, england. - `value_min` (query, optional) — Minimum stated contract value in GBP. - `value_max` (query, optional) — Maximum stated contract value in GBP. - `deadline_after` (query, optional) — Only notices whose submission deadline is on or after this date (YYYY-MM-DD). - `stage` (query, optional) — tender (open competitions, default both) or planning (early engagement). ### POST /v1/tenders/fit-score — $0.20 Send a supplier profile (what you do, keywords, regions, value band, certifications) and get the best-fitting live UK tenders, each scored 0-100 by deterministic published rules across five factors - relevance, value fit, geography, timeline, buyer history - each with its numerator AND denominator so you can re-weight client-side, plus a what-to-emphasise note on the top matches. Rules score; a model never does. Returns: result = { considered, matches[] of { ...notice brief..., fit: { score, band strong|possible|weak, factors{ relevance/of, value_fit/of_v, geography/of_g, timeline/of_t, buyer_history/of_b }, flags[], rules_version }, emphasise } }. ### GET /v1/tenders/{ocid}/brief — $0.10 One tender as a full agent-ready dossier: parsed requirements summary, buyer, value, complete timeline with working-days-remaining, lots, document links, submission route and the official notice URL. CPV codes are null when the source release carries none - we report the register, we never guess. Returns: result = { ocid, title, buyer, value, stage, published, deadline, days_remaining, region, cpv, summary, description, lots, documents[], submission_url, timeline{}, source{} }. Parameters: - `ocid` (path, required) — The OCDS contracting-process id, e.g. ocds-h6vhtk-06df8b (FTS) or ocds-b5fd17-… (Contracts Finder). Exactly as returned by /v1/tenders/search. ### GET /v1/grants/search — $0.10 Live UK grant funding calls from GOV.UK Find a Grant in one call: name, funder, amount range, opening/closing dates, who can apply, one-line summary and the official source link. Filter by keywords, nation, applicant type and amount band. Indexed daily from the official listing - the service has no API of its own, so this is the machine-readable version. Returns: result = { total_matched, returned, grants[] of { id, name, funder, amounts{min,max,text}, window{opens,closes,open_now,days_to_close}, who_can_apply, org_types, regions, summary, criteria_parsed, criteria_basis seed|llm|listing|null, source_url }, excluded{} }. Parameters: - `q` (query, optional) — Keywords matched against grant names, summaries, funders and descriptions (light stemming). At least one criterion is required. - `region` (query, optional) — UK nation: england, scotland, wales, northern-ireland (or uk for UK-wide only). - `org_type` (query, optional) — Applicant type: individual, business, charity, community_group, public_body, local_authority, education (synonyms like sole-trader, cic, council are mapped). - `min` (query, optional) — Only grants whose maximum award is at least this many GBP. - `max` (query, optional) — Only grants whose minimum award is at most this many GBP. - `open_now` (query, optional) — Default true: only grants currently open for applications. Set to false to include closed/not-yet-open listings. ### POST /v1/grants/match — $0.15 Send a project profile (what it is, who you are, where, how much you need) and get back the live UK grants it could actually get - ranked eligible-first with a per-criterion pass/fail table for every match, from criteria parsed once at ingest from each grant's own eligibility text. Ineligible grants are excluded and counted, never dressed up as options. Deterministic rules; no language model touches the verdicts. Returns: result = { considered, matches[] of { grant summary + eligibility { band eligible|uncertain, score, criteria[{code,requirement,pass,detail}], missing[], flags[] } , relevance }, excluded{ineligible, closed} }. ### GET /v1/grants/{id}/eligibility — $0.15 One grant, one project: a deterministic eligibility verdict with the full criteria table - each criterion quoted from the grant's own eligibility text, marked pass/fail/undeclared - plus what is missing to firm it up and indicative funding. Criteria are parsed once at ingest, never guessed at request time; if the full text is not parsed yet the verdict uses Find a Grant's listing fields, flagged PARTIAL_CRITERIA, and criteria_provenance says so. Returns: result = { grant{name,funder,window,amounts,source_url}, criteria[{code,requirement,pass,detail}], missing[], failed[], indicative_funding, criteria_provenance{source,complete,parsed_at,eligibility_text_available} }, verdict = { score, band eligible|uncertain|ineligible, flags[] }. Parameters: - `id` (path, required) — Grant id: the Find a Grant slug exactly as returned by /v1/grants/search (e.g. england-woodland-creation-offer-ewco-1), or a curated short alias like ewco. - `org_type` (query, optional) — Applicant type slug (individual, business, charity, community_group, public_body, local_authority, education). - `region` (query, optional) — Where the project is: england, scotland, wales, northern-ireland. ### GET /v1/funders/{name} — $0.20 Who actually funds things like yours: one UK funder's giving history aggregated from the 360Giving open-data corpus - grants made, total and typical award, size distribution, yearly pattern, most recent named awards - plus any of their grant schemes live on Find a Grant right now. Licences are respected per dataset (share-alike data is excluded from the numbers, and every recent-award row carries its source licence). Returns: result = { funder{name,ids}, match_quality, giving { grants_made, total_awarded_gbp, years, size_distribution_gbp{min,p25,median,p75,max,mean}, yearly{}, typical_award_gbp }, recent_awards[] (each with licence + publisher), live_grants_now[], coverage }. Parameters: - `name` (path, required) — Funder name or slug, e.g. national-lottery-heritage-fund, "Esmée Fairbairn Foundation", or a GB-CHC-… org id. ## Free endpoints - `GET /v1/health` — Liveness and upstream health. Free, because frameworks probe before they route money. - `GET /v1/preview` — A genuine, freshly-computed sample so an agent can see the exact response shape before spending anything. Default: a real company verdict, rotating daily. Add ?wing=tenders for a real live-tender brief, or ?wing=grants for a real grant eligibility verdict - all rotating daily. Every response carries the same envelope: query, result, verdict, confidence, as_of, sources, attribution, notice, cost. - `POST /v1/feedback` — Agent wish-list intake. Send { message, endpoint?, contact? } and it lands in our inbox. Free, and it directly shapes what gets built next. Probe before you route money: `GET https://api.ukintel.uk/v1/preview` returns a real, freshly-computed company verdict, `GET https://api.ukintel.uk/v1/preview?wing=tenders` a real live tender brief, and `GET https://api.ukintel.uk/v1/preview?wing=grants` a real grant eligibility verdict - all rotating daily, in the exact paid response shape, for nothing. ## MCP Every endpoint above is also an MCP tool at `https://api.ukintel.uk/mcp` (Streamable HTTP, POST-only, JSON responses). Add it to any MCP client and the wings appear as 13 tools: 11 paid, 2 free. Paid tools use the same x402 terms as the HTTP routes: call the tool, receive a payment-required result carrying the accepts array, pay, retry with the payment in `_meta["x402/payment"]`. An x402-aware MCP client does this for you; prices are stated in every tool description so an agent can decide before it calls. `uk_preview` and `uk_health` are free, so a client can list tools and see a real answer before any wallet is involved. ## How the company verdict score is computed (Wing 1) Rules version 1.0.0. Every score is produced by the deterministic table below - a language model writes the `narrative` field and nothing else. Score starts at 100, deductions apply, then any status cap is applied, then the result is clamped to 0-100. | Flag code | Trigger | Effect | |---|---|---| | STATUS_DISSOLVED | Companies House status is dissolved, converted-closed, removed or closed | cap score at 5 | | STATUS_ADMINISTRATION | Companies House status is administration, liquidation, receivership or insolvency-proceedings | cap score at 20 | | STRIKE_OFF_ACTIVE | Status detail is active-proposal-to-strike-off | cap score at 35 | | ACCOUNTS_OVERDUE | Annual accounts are past their due date and not filed | -25 | | CONF_STATEMENT_OVERDUE | Confirmation statement is past its due date and not filed | -15 | | YOUNG_COMPANY | Incorporated less than 12 months ago | -10 | | DORMANT | Latest accounts filed are of type dormant | -10 | | OFFICER_CHURN | Two or more officer resignations in the trailing 12 months | -10 | | NO_ACTIVE_DIRECTORS | Zero active directors listed | -20 | | FS_SIC_NOT_FCA | A SIC code in the 64/65/66 financial-services range with no match on the FCA register (only applied when the FCA register was actually consulted) | -20 | | FCA_WARNING | On the FCA register with restrictions or warnings | -15 | | CHARGES_INFO | Outstanding charges registered - informational only, normal for financed firms | informational only (0) | | STATUS_VOLUNTARY_ARRANGEMENT | Companies House status is voluntary-arrangement (a formal insolvency procedure) | -25 | | INSOLVENCY_HISTORY | Register records prior insolvency history - informational only | informational only (0) | | OFFICERS_UNAVAILABLE | Officer data could not be fetched - the two officer rules are skipped and confidence drops | informational only (0) | Bands: 80-100 low_risk · 50-79 caution · 0-49 high_risk. ## How the tender fit-score is computed (Wing 2) Tender rules version 1.0.0. Deterministic rules compute every fit-score; a language model writes the one-sentence `emphasise` note for top matches and nothing else. Every factor returns its numerator AND denominator so you can re-weight client-side. | Factor | Weight | Rule | |---|---|---| | RELEVANCE | 40 | Keyword/phrase overlap between supplier profile and notice title+description - title hits weighted, simple stemming, synonym-expanded via our published keyword stack. When the notice carries CPV codes, 8 of the 40 ride on CPV agreement; when it carries none (honest null), text carries the full weight - the source's gap is never your penalty. | | VALUE_FIT | 20 | Notice value inside your declared band -> 20; within 2x either side -> 10; value or band unstated -> 8 (neutral). | | GEOGRAPHY | 15 | Notice delivery region matches a region you serve -> 15; unstated on either side -> 8 (neutral); stated mismatch -> 0. | | TIMELINE | 10 | >= 10 working days to deadline -> 10; 5-9 -> 5; fewer -> 0 + DEADLINE_TIGHT flag. Working days = Mon-Fri (bank holidays not yet excluded - documented, not hidden). | | BUYER_HISTORY | 15 | v1 ships a neutral 8 for every buyer - honestly flagged here rather than silently invented. Buyer award-history enrichment is this wing's first planned upgrade. | Bands: 75-100 strong · 50-74 possible · below 50 weak. A notice must earn at least 8/40 RELEVANCE to be listed as a match at all - neutral points on the other factors never dress up an irrelevant notice (excluded notices are counted in `below_relevance_floor`). Search relevance uses the same matching core, so /search and /fit-score can never disagree about what matches. ## How the grant eligibility verdict works (Wing 3) Grant rules version 1.0.0. Each grant's published eligibility text is parsed ONCE at ingest into a structured criteria table (applicant types, regions, numeric thresholds, declarations) - a language model does that single conversion and is never involved at request time. Your profile is then evaluated by pure rules: - any HARD criterion fails -> band `ineligible`, score 0, the failing codes in `failed[]`; - no fails -> band `eligible`; score = share of criteria affirmatively passed (an undeclared fact counts half and is listed in `missing[]` with a MISSING_DECLARATION flag - declare it and re-check); - criteria unparsed or nothing declarable -> band `uncertain` + UNPARSED_CRITERIA / NOTHING_DECLARED. We never guess: the raw eligibility text stays one click away at `source_url`. Where a grant's full text is not parsed yet, the verdict falls back to Find a Grant's own published `Who can apply` and `Location` fields and says so with a PARTIAL_CRITERIA flag. Those fields are the funder's own categorisation, so they can return `ineligible` with confidence - but they are not the whole rulebook, so a partial assessment is never promoted to `eligible`. `result.criteria_provenance` states exactly what each verdict was computed from (`complete: true|false`), and `/v1/health` publishes live coverage as `grants_index.with_criteria` and `grants_index.awaiting_criteria`. Profile vocabulary - org_type: individual | business | charity | community_group | public_body | local_authority | education (synonyms like sole-trader, cic or council are mapped). region: uk | england | scotland | wales | northern-ireland. Numeric facts go straight in the query string, e.g. `land_ha=3.5&min_width_m=25`; yes/no declarations as `management_control=true`. Criteria name the exact param they read, so a first call tells you what to declare on the second. Funder dossiers aggregate 600 of 877 datasets from the 360Giving registry (refreshed monthly; CC-BY-SA datasets excluded from the numbers by policy, exclusions counted in the response). Every recent-award row carries its source dataset's licence. ## Data sources, freshness and licensing - Companies House Public Data API — fetched live, cached 6 hours per company number. - FCA Financial Services Register — consulted per company, cached 24 hours. - Find a Tender + Contracts Finder (OCDS feeds) — indexed on a 6-hour cycle; `as_of` on tender responses is the last successful ingest, and an index older than 12 hours drops confidence to medium with an INGEST_STALE flag. CPV codes are null when the source release carries none - we report the register, we never guess. Our summaries are rephrasings: the official notice URL travels in every response so you can verify against source. - GOV.UK Find a Grant — the service has no API, so we index it by polite daily scrape (sequential, identified user-agent, robots.txt honoured on every cycle; if robots ever disallows us we stop and say so with a SCRAPE_BLOCKED flag). Grant listings change slowly; `as_of` is the last successful daily refresh. Fresh deployments serve a bundled snapshot flagged INDEX_SEED until the first live cycle. - 360Giving publisher datasets — refreshed monthly via the GrantNav datasets registry, aggregated per funder. Per-dataset licences are stored and surfaced; CC-BY-SA datasets are excluded from aggregate numbers entirely. Dossiers name the datasets and coverage they rest on - they describe the published corpus, never the whole sector. - Contains public sector information licensed under the Open Government Licence v3.0 (Companies House). - FCA register data (c) FCA. - Contains public sector information licensed under the Open Government Licence v3.0 (Find a Tender / Contracts Finder). - Contains public sector information licensed under the Open Government Licence v3.0 (GOV.UK Find a Grant). - Historical grants data: 360Giving publishers, mixed open licences (mostly CC BY 4.0, some CC0/OGL) - attribution per dataset, carried in every funder response. - Information, not advice. We return public register facts and rules-based scores, not advice. A fit-score means fit, never "you will win" - and a grant eligibility verdict means the stated criteria pass, never "you will get this grant": eligibility is not award, and the funder's assessment decides. Officer names and dates of birth are deliberately not returned. Officer counts and resignation churn are. ## Something missing? `POST https://api.ukintel.uk/v1/feedback` with `{ "message": "..." }` is free and read by a human. It is the fastest way to get a field added.