DEV Community

ukintel
ukintel

Posted on

ukintel.uk: UK company, tender and grant data as paid JSON for agents

UK public registers are free and public. Companies House, the FCA register,
Find a Tender, Contracts Finder, GOV.UK Find a Grant. All of it is open data
under the Open Government Licence, and none of it is usable by an AI agent
without a human in the loop.

Companies House needs an API key from a human dashboard. The FCA Register
API needs a developer account and written permission. Find a Tender publishes an OCDS feed with no keyword
search at all. GOV.UK Find a Grant has no API of any kind — it is HTML, and
that is the whole interface. An agent that tries to do this itself either
stops at a signup form or starts scraping.

api.ukintel.uk is those five sources behind eleven x402 endpoints. Call it,
get a 402 with payment terms, pay in USDC on Base, retry. No account, no API
key, no rate-limit negotiation.

The arithmetic

This is the part worth checking rather than believing.

An agent answering "is this UK supplier legitimate?" by browsing does roughly
five page-loads — Companies House search, company profile, filing history,
officers, FCA register — about 34,000 input tokens, plus ~2,500 tokens of
tool-call overhead and ~2,500 output tokens of reasoning.

On a mid-tier model at $2/M in and $10/M out, that is $0.098 per attempt.
Apply a realistic 30% retry-and-blocked-page factor and it is ~$0.13,
taking 30–90 seconds. On a frontier model at $10/M and $50/M it is $0.49 per
attempt, ~$0.64 with retries
.

GET /v1/company/{number}/verdict costs $0.10 and returns roughly 800
structured tokens. Reading them costs $0.0016–$0.008 depending on the model.
Call it $0.102–$0.108, in about two seconds.

So: modestly cheaper on a mid-tier model, roughly 6× cheaper on a frontier
model
, and in both cases the DIY route also burns ~36,000 tokens of context
the agent needed for the rest of its task.

There is a sharper version of this. A raw Companies House filing-history JSON
for a mid-sized company is about 60KB — around 15,000 tokens. Merely reading
that free file costs $0.030 on a mid-tier model and $0.150 on a frontier
model
, every single time, before any thinking happens. The verdict endpoint
costs $0.10 all-in and has already done the judgement. On frontier models the
paid answer is cheaper than the free data.

That is the entire product thesis: sell fewer tokens that say more.

What it actually returns

Every endpoint returns the same envelope — query, result, verdict,
confidence, as_of, sources, attribution, notice, cost. Deterministic
key order, explicit nulls rather than missing keys, no HTML anywhere, ~800
tokens by default with ?detail=full to lift the cap.

as_of is when we fetched the underlying data, never when you asked.

Here is a real grant eligibility verdict, returned free from
/v1/preview?wing=grants today — a live DfE school-based nursery capital
grant against a showcase project profile:

"verdict": {
  "score": 64,
  "band": "eligible",
  "flags": [
    { "code": "MISSING_DECLARATION",
      "detail": "net_increase_childcare_places not declared; Proposed project will result in a net increase in the number of childcare places, accounting for existing provisions on site or nearby" },
    { "code": "MISSING_DECLARATION",
      "detail": "landowner_permission not declared; Written permission from relevant freehold landowner to use land for nursery provision and carry out proposed works" },
    { "code": "REVIEW_REMAINING",
      "detail": "3 criteria cannot be auto-assessed (OPERATIONAL_BY_SEPTEMBER_2030, PROJECT_CLASSIFICATION, PREVIOUS_GRANT_ADDITIONALITY) - review them against the source page." }
  ],
  "rules_version": "1.0.0"
}
Enter fullscreen mode Exit fullscreen mode

Note what it does not do. It does not guess. score: 64 is not confidence in
eligibility — it is the share of criteria affirmatively passed, with undeclared
facts counting half and named in missing[]. Declare them and call again and
the score firms up. A criterion nobody can auto-assess says so and points at
the source page.

The rules are published. Any hard criterion failing means ineligible, score
0, failing codes listed. No fails means eligible. Unparseable criteria means
uncertain — never a fabricated verdict.

Where the language model is, and is not

A language model writes the optional two-sentence narrative field on company
verdicts, the one-sentence emphasise note on top tender matches, and it
performs a single text-to-criteria conversion once per grant at ingest time.

It touches no score, on any endpoint, ever. Every 0–100 number comes from a
deterministic rule table that ships in the docs, versioned, with each rule that
fired named in the response. You can audit any score by hand, and you can
disagree with a rule and re-weight it — the tender fit-score returns every
factor's numerator and denominator so you can re-weight client-side without
calling us again.

This is a deliberate constraint, not a limitation we are apologising for. A
score an agent cannot audit is a score an agent should not act on.

The endpoints

Endpoint Price What it answers
GET /v1/company/search $0.005 Find a UK company by name
GET /v1/company/{number} $0.02 Structured profile, filing dates, officer counts
GET /v1/company/{number}/verdict $0.10 0–100 legitimacy verdict, named flags
GET /v1/company/{number}/fca $0.02 FCA register status only
GET /v1/tenders/search $0.05 Live UK tenders as briefs
GET /v1/tenders/{ocid}/brief $0.10 One tender, full dossier
POST /v1/tenders/fit-score $0.20 Supplier profile → scored matches
GET /v1/grants/search $0.10 Live GOV.UK grant calls
POST /v1/grants/match $0.15 Project profile → eligible grants, ranked
GET /v1/grants/{id}/eligibility $0.15 One grant, one project, criteria table
GET /v1/funders/{name} $0.20 Funder giving history from 360Giving

Free, because frameworks probe before they route money: /v1/health,
/v1/preview (a real, freshly-computed sample in the exact paid shape,
rotating daily — add ?wing=tenders or ?wing=grants), and /v1/feedback.

Also available as an MCP server at https://api.ukintel.uk/mcp (13 tools,
listed in the official MCP registry as uk.ukintel/ukintel).

Freshness, and what we are honest about

Companies House is fetched live, cached six hours per company number. Find a
Tender and Contracts Finder are indexed on a six-hour cycle — 3,590 notices
right now; an index older than twelve hours drops confidence to medium and
raises an INGEST_STALE flag rather than quietly serving old data. Find a
Grant is a polite daily scrape — sequential, identified user-agent, robots.txt
honoured every cycle, and if robots ever disallows us we stop and say so with
a SCRAPE_BLOCKED flag.

Three things we would rather you heard from us than discovered:

  • The FCA cross-check runs against the Register's beta API. We hold written permission from the FCA Register API team for this use (real-time lookup, status/FRN/register-link only, attributed, nothing stored). Their own caveat applies: the API is beta with limited support, so if it does not answer, the endpoint degrades honestly — fca.checked: false, the financial-services rules are skipped, and no FCA claim is made. We never assert "not regulated" from a failed lookup, only from a successful lookup that found nothing.
  • Grant criteria come at two depths, and the response tells you which one answered. Every indexed grant is assessed against Find a Grant's own published "Who can apply" and "Location" fields, so a clearly ineligible applicant is ruled out anywhere in the corpus. Most grants also have their full eligibility text parsed into a criteria table — thresholds, declarations and all — and only a grant at that depth can come back eligible. A listing-only assessment is flagged PARTIAL_CRITERIA and stays uncertain rather than being talked up, because those two fields are not the whole rulebook. result.criteria_provenance.complete says which you got. Coverage is public rather than a number we are asking you to trust: GET /v1/health reports grants_index.with_criteria and grants_index.awaiting_criteria against grants_index.grants (today: 109 of 120 at full depth).
  • Tender buyer-history scores a neutral 8/15 for every buyer in v1. It is flagged in the response and documented in the rules table rather than silently invented. Buyer award-history is this wing's first planned upgrade.

CPV codes are null when the source release carries none. We report the
register; we do not guess.

Licensing

Companies House, Find a Tender, Contracts Finder and Find a Grant are Open
Government Licence v3.0, attributed in every response. 360Giving publisher
datasets carry mixed open licences — the funder corpus aggregates 516 of 874
published datasets across 229 funders, CC-BY-SA datasets are excluded from the
numbers entirely by policy, exclusions are counted in the response, and every
recent-award row carries its own source licence. Dossiers describe the covered
corpus, never the whole sector.

Officer names and dates of birth are deliberately not returned. Officer counts
and resignation churn are.

Try it without paying

curl https://api.ukintel.uk/v1/preview
curl https://api.ukintel.uk/v1/preview?wing=tenders
curl https://api.ukintel.uk/v1/preview?wing=grants
Enter fullscreen mode Exit fullscreen mode

Real data, freshly computed, rotating daily, in the exact shape the paid
endpoints return.

If you use Claude Code, one line connects all 13 tools:

claude mcp add --transport http ukintel https://api.ukintel.uk/mcp
Enter fullscreen mode Exit fullscreen mode

Machine docs: /llms.txt · /openapi.json · /.well-known/x402 ·
/.well-known/agent-card.json · MCP at /mcp

Something missing? POST /v1/feedback with {"message": "..."} is free, read
by a human, and is the fastest way to get a field added. Or email
hello@ukintel.uk.

Information, not advice. These are public register facts and rules-based
scores. A fit-score means fit, never "you will win". 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.

Top comments (0)