Product

Know who to look at.
Know when to act.

Everything here does one of those two jobs. Resolve and Graph tell you which company you are looking at and what it is connected to. Watch, Sync and Grounding make sure every system you run finds out the day that changes.

INPUT"nordw1nd logistik g.m.b.h"ent_01JR8K3F5T2QW9one key, addressed five ways01Resolvematches the input0.987confidence · auto-accepted02Entity Graphreturns the record184attributes · HRB 14890203Watchreports a change1 filingofficers changed, 04:47 UTC04Syncmirrors it downstream1 rowupdated in Snowflake05Groundinghands it to a model1 citationsrc_01JV3D8K1P6NQZ
01 · Resolve

Four scorers, one decision

Four independent scorers run over a blocked candidate set and are combined by a calibrated model. You get the winner, the runners-up, and the reason — so a low-confidence match becomes a review task instead of a silent error.

  • Any input type. Free text, domain, email domain, VAT, LEI, DUNS, register number, EUID, brand name, former name, OCR line, postal address.
  • Calibrated confidence. A 0.91 means it is right about 91% of the time. We refit the calibration monthly against SPOT-Bench and publish the residuals.
  • Per-key thresholds. KYB wants 0.99 and a human on everything else. CRM dedup runs happily at 0.90. Both are one setting.
  • Explainable. Every response carries per-scorer contributions and the fields that agreed or conflicted.
candidates · q = "nordw1nd logistik g.m.b.h"12 scored
EntityLexicalEmbeddingRegistry keyGeoScoreDecision
Nordwind Logistik GmbH
ent_01JR8K3F5T2QW9 · HRB 148902
0.910.960.980.987auto_accept
Nordwind Kontraktlogistik GmbH
ent_01JQ9V2H7YB4KC · HRB 204117
0.840.900.980.881review
Nordwind Logistik Bremen (branch)
ent_01JQ8B4X2VT7RC · HRB 148902-B1
0.790.830.410.642no_match
Nordwerk Logistik GmbH
ent_01JW2K6D9NF3PB · HRB 331507
0.740.710.220.518no_match
The registry-key scorer stays silent here — the OCR'd input carries no register number, so three of the four decide it. Eight further candidates below 0.50 are suppressed.44 ms · eu-central-1
02 · Entity Graph

The record behind the ID

The graph is what makes the ID worth having. Ownership chains, branch networks, brand portfolios and administrative geography are typed relations — so you can roll a portfolio up to its ultimate parent, or count every entity in a Swiss commune, in one call.

Attribute groupFieldsPrimary sourcesPopulated
Identity & status21National registers, BRIS100%
Identifiers14GLEIF, VIES, register, RDAP96%
Address & geography19Register, LAU/NUTS, national gazetteers99%
Classification11NACE 2.1, SIC, national codes93%
Financials38Bundesanzeiger, Companies House, Registro Imprese61%
Relations17Register filings, group accounts74%
Brands & marks23EUIPO TMview, WIPO GBD, USPTO91%
Web & digital26RDAP, CT logs, DNS, sitemaps81%
Events & history15Gazettes, announcement feeds97%
graph · ent_01JR8K3F5T2QW9depth 2 · 6 edges
owns 100%branchesholds markseated inentNordwind Holding AGHRB 91044 · parententNordwind Logistik GmbHHRB 148902entNordwind KontraktlogistikHRB 204117 · 100%entSandtorkai GrundbesitzHRB 118330 · 74.9%br2 branchesBremen · RotterdambrdNordwind ExpressEUIPO 018112447geoHamburg-MitteAGS 02000 · LAU DE600
Six of the 1.9 billion edges in the graph. Every node is addressable by its own ID, so you can roll a portfolio up to its ultimate parent or count every entity seated in a commune.
as_of · same entity, three dates
2018-01-01Nordwind Spedition GmbH€41.2M168 staff
2022-01-01Nordwind Logistik GmbH€72.9M301 staff
2026-09-05Nordwind Logistik GmbH€98.4M412 staff
Every read accepts ?as_of=, so point-in-time reads are a query parameter rather than a quarterly snapshot job.
03 · Watch

Change events

Subscribe to an entity list or to a saved query — “any DE logistics company over €50M that files an insolvency notice”. Signed webhooks, at-least-once delivery, 7-day replay, and a dead-letter queue you can drain.

Event typeFires onVolume / mo
entity.name_changedRegister name amendment61,400
entity.status_changedLiquidation, dissolution, reactivation248,900
entity.insolvency_filedCourt insolvency notice9,120
entity.officer_changedDirectors, managers, signatories412,700
entity.capital_changedShare capital increase or reduction38,500
entity.address_changedRegistered seat relocation154,300
entity.financials_filedNew annual accounts published643,000
entity.mergedMerger, split, cross-border conversion14,600
query.entered / query.exitedEntity enters or leaves a saved query

31 event types in total.

POST https://hooks.acme.example/spotitsigned · sha256
{
  "event_id": "evt_01JXR4T8M2C9KD",
  "type": "entity.officer_changed",
  "occurred_at": "2026-03-11T00:00:00Z",
  "observed_at": "2026-03-11T04:47:31Z",
  "entity_id": "ent_01JR8K3F5T2QW9",
  "subscription_id": "sub_01JH9F2Q7XB4NM",
  "change": {
    "field": "relations.officers",
    "before": { "count": 2 },
    "after":  { "count": 3 }
  },
  "source": {
    "authority": "Amtsgericht Hamburg",
    "document": "src_01JXQ0W5R8T2LP",
    "gazette": "HRB 148902 / 2026-03-11"
  }
}

Delivery p95 is 2.4 s from ingest; ingest median is 4.2 h from register publication.

At-least-onceRetries at 1s, 5s, 30s, 5m, 1h, 6h
7-day replayRe-deliver any window by subscription
SignedHMAC-SHA256, rotating secret, 5-min tolerance
Or pollGET /v1/events?since=cursor
04 · Sync

Warehouse and CRM delivery

A Snowflake or BigQuery share that refreshes hourly. A dbt package with the join macros written. A Salesforce field map that writes the entity ID back onto the Account object. The pipeline is ours to run.

DestinationMechanismRefreshWrites back
SnowflakeSecure data share (EU / US)hourly
BigQueryAnalytics Hub listinghourly
DatabricksDelta Sharinghourly
PostgresLogical replication slotstreaming
SalesforceManaged package, field map15 minentity ID, name, status
HubSpotApp + property map15 minentity ID, domain, NACE
dbtspotit_core packageon run
Fivetran · AirbyteCertified source connector6 h
Clay · n8n · Zapier · RetoolNative blockson demandconfigurable

The nine rows above are the connectors we build and support ourselves; the rest are community-maintained against the OpenAPI spec. Full list.

warehouse · dedupe an account tableSQL
-- the spotit share is mounted as SPOTIT.CORE
with resolved as (
  select a.account_id, r.entity_id, r.confidence
  from analytics.crm_accounts a,
       table(SPOTIT.CORE.resolve(a.raw_name, a.country)) r
  where r.confidence >= 0.90
)
select
  e.entity_id,
  e.name as canonical_name,
  count(*) as crm_rows,
  array_agg(v.account_id) as collapse_into
from resolved v
join SPOTIT.CORE.entities e using (entity_id)
group by 1, 2
having count(*) > 1
order by crm_rows desc;
Typical first run on a 240k-row CRM: 233,637 matched rows resolve to 189,477 distinct entities — 44,160 duplicates.
SPOTIT.CORE · what lands in the warehouse
entities418.6M rows · one per canonical entity
identifiersLEI, VAT, EUID, register number, domain
relations1.9B edges · parent, branch, brand, commune
eventsRegister filings from 2009, one row each
lineageField to source document, with observed_at
05 · Grounding

Tools that return citations

An LLM will produce a company name, a registration number and a revenue figure with equal confidence, and only one of them will be checkable. spotit is the tool call that makes all three checkable — and it is wired into every framework in the table below.

  • MCP server. Hosted at mcp.spotit.ai/sse, or run it locally with npx @spotit/mcp. Seven tools, scoped by API key.
  • OpenAI-compatible tool schemas. Drop-in JSON for function calling, Anthropic tool use, Vertex, Bedrock and Azure AI Foundry.
  • Framework adapters. LangChain, LlamaIndex, Mastra, Pydantic AI, Vercel AI SDK, CrewAI, Semantic Kernel.
  • Test keys. A spk_test_ key reads the full graph, caps at 500 calls a day and is never billed, so an eval suite costs nothing to run.
  • Citations included. Every tool result carries entity_id, source and observed_at, so your evaluator can grade groundedness without a second retrieval pass.
~/.config/mcp/servers.json
{
  "mcpServers": {
    "spotit": {
      "url": "https://mcp.spotit.ai/sse",
      "headers": {
        "Authorization": "Bearer spk_test_..."
      }
    }
  }
}
tools exposed7
spotit_resolve_entityMessy input → entity ID + confidence
spotit_get_entityFull record, optionally as_of a date
spotit_searchStructured filters: sector, geo, size, form
spotit_eventsRegister events for a set of entities
spotit_lineageSource document behind any field
spotit_relationsWalk parents, subsidiaries, branches, brands
spotit_geoCommunes, districts, NUTS/LAU rollups

Where the data comes from

Tier 1 is primary-register ingest with the full event history. Tiers 2 and 3 narrow to identity and identifiers, and the cards below say exactly which fields each one carries.

Tier 159 jurisdictions

Ingested from the primary register, with the full event history behind every field.

Fields carriedIdentity · identifiers · officers · relations · events · financials where filed
Share of all entities71.4%
IncludesGermany, UK, France, Netherlands, Japan
Tier 276 jurisdictions

Assembled from official sources that publish identity but not a full filing stream.

Fields carriedIdentity · status · identifiers · addresses
Share of all entities26.9%
IncludesUnited States, Poland, Saudi Arabia, Nigeria
Tier 357 jurisdictions

Identity only, from official aggregates and international registers.

Fields carriedIdentity · jurisdiction · LEI where issued
Share of all entities1.7%
IncludesIraq, Angola, Tajikistan, Greenland
jurisdiction table8 of 192 · sorted by entity count
JurisdictionLegal entitiesPrimary registerFiled financialsMedian freshnessTier
United States41,209,77450 SoS registries · SEC EDGAR9%27 hTier 2
Germany6,412,880Handelsregister · Bundesanzeiger88%3.1 hTier 1
United Kingdom5,704,119Companies House94%1.4 hTier 1
France4,988,301INPI RNE · INSEE SIRENE71%6.8 hTier 1
Italy3,146,902Registro Imprese79%9.4 hTier 1
Poland2,905,441KRS · CEIDG57%11 hTier 2
Netherlands2,381,660KVK Handelsregister64%5.0 hTier 1
Switzerland762,455Zefix · SHAB22%2.2 hTier 1
Freshness is the median lag from a register publishing a change to it being readable on the API, measured over the last 90 days. Browse all 192
Use cases

What teams do with it

Six workflows, one underlying question: is this the same company as that one, and what is true about it today?

M&A sourcing

Screen the register directly

Define the universe with the filters that correlate with a deal — NACE code, revenue band, headcount trajectory, legal form, shareholder concentration, incorporation vintage, commune. Dedupe against your pipeline by entity ID, then put Watch on the survivors.

  1. 1Screen the register
  2. 2Dedupe against the pipeline
  3. 3Watch the survivors

Signals teams subscribe to: officer change, capital increase, first-time filing of consolidated accounts, new branch abroad, auditor change, insolvency of a customer or supplier in the same graph.

GET /v1/search34,108 results · 91 ms
{
  "jurisdiction": ["DE", "AT", "CH"],
  "nace": ["28.4", "28.9", "25.6"],
  "revenue_eur": { "gte": 10e6, "lte": 80e6 },
  "headcount": { "gte": 50 },
  "legal_form": ["GmbH", "GmbH & Co. KG"],
  "incorporated_before": "2005-01-01",
  "has_parent": false,
  "status": "active"
}
Owner-operated DACH machining, €10–80M, 20+ years old, no group parent.
CRM hygiene & deduplication

The join key you never had

Batch-resolve the whole account table once. Rows sharing an entity ID are duplicates by definition — no fuzzy-match tuning, no merge-rules committee. Then keep it clean: Watch pushes name changes, status flips and seat relocations back through the managed package so nobody hand-edits an Account again.

  1. 1Batch resolve
  2. 2Collapse by ID
  3. 3Write the ID back
  4. 4Subscribe to changes

What the review queue contains: mostly holding companies that share a name with their operating subsidiary, and branches filed under a parent’s register number. Both are real ambiguities, which is why they are not auto-accepted.

job_01JYD3K8P2M6TQ · 240,118 rowscomplete · 11m 42s
Rows submitted240,118
Auto-accepted208,90487.0%
Sent to review24,73310.3%
No match6,4812.7%
Distinct entities behind the matches189,477
Duplicate rows (233,637 matched − 189,477 entities)44,16018.4%
Dissolved / inactive accounts3,9181.6%
Names now stale in CRM7,2043.0%
Cost of this run: 240,118 credits — €546 of overage on Team.Pricing
AI grounding

Retrieval keyed on identity

Index your documents against entity IDs and a query about “Nordwind Spedition” finds the 2024 contract filed under “Nordwind Logistik GmbH”. Agents that can call the register stop inventing registration numbers. And because every result carries a source and a timestamp, groundedness becomes a metric you can compute.

  1. 1Resolve at ingest
  2. 2Key chunks by ID
  3. 3Expose the tools
  4. 4Grade with citations
internal eval · company-fact QA, n = 1,200
ConfigurationExact-fact accuracyUnsupported claims
Model alone, no tools41.8%38.2%
Web search tool67.4%14.9%
Name-matched RAG over filings72.1%11.6%
spotit tools, ID-keyed94.6%1.3%
Our benchmark, our questions — published with the harness so you can rerun it.Method

Bring a messy CSV.
Leave with entity IDs.

Upload 1,000 rows on the free tier or 10,000 on Team. You get a match report with confidence bands, duplicates and stale names back before you write any code.

Free tier upload
1,000 rows
Team upload
10,000 rows, ~30 s
Report contains
entity ID, confidence, duplicates
Card required
no