firmus.sh

Company data your assistant can cite.

Add Firmus to Claude, attach a CRM or supplier export, and ask. Each row comes back either identified by its SIREN, with the fields the match rests on and the columns you asked for, or marked ambiguous or not found — never a guess. Every value names the register it came from and the date that register last changed it.

In Claude's connector settings, add a custom connector with this URL.

connector URL
https://api.firmus.sh/mcp

Then attach the file and ask

Identify the companies in this file, then add their activity, workforce band and head office city as new columns. Give me the result as a CSV.

A file in, the same file back, no row guessed.

Claude sends the rows to resolve, which names the company behind each one or says it cannot, then to enrich, which adds the columns you asked for. A whole file goes to submit_job and comes back as your CSV: every line and column kept, Firmus's columns appended.

# crm_export.csv, as attached
Company;Zip
Danone SA;75009
Boulangerie Martin;
Zzyzx Quantum Holdings;69002
CompanyZipfirmus_resolve_statusfirmus_resolve_confidencefirmus_registry_numberfirmus_matched_namefirmus_activity_labelfirmus_data_updated_at
Danone SA75009matched0.925552032534DANONEActivités des sièges sociaux2026-04-10T11:28:37Z
Boulangerie Martinambiguous0.750
Zzyzx Quantum Holdings69002not_found0.000

Recorded on 2026-11-01 on a copy of the register's publication of 2026-08-01; six of the appended columns shown. A row the match cannot settle is ambiguous and lists up to three candidates instead of picking one, and a name nothing matches is not_found: neither is a guess. An empty cell is written empty, as in the file.


Four tools, and a source on every answer.

Claude picks the tool from what you ask. Every answer names the register it read and the date of what it says, so Claude can cite rather than assert.

resolve
Looks for the French company behind each row — a name with a postal code or a city, an address, a VAT number, a SIREN or a SIRET. A row it can settle comes back with the SIREN, a confidence and the fields the match rests on; one it cannot comes back ambiguous, with its candidates, or not found. Never a guess.
enrich
Adds the columns you choose to identified companies: name, legal form, activity, workforce band, head office, active establishments, and the latest event of each kind. Each row carries the date the register last changed the company.
timeline
Lists what the register recorded about one company and its establishments, newest first, each event with the date it happened and the date Firmus recorded it.
lookup
Fetches one company by SIREN, or one establishment by SIRET: status, legal form, activity, workforce band, dates and address, with the date the register last changed the record.

A file too large for one call goes to submit_job, which answers with a job id rather than the rows, and job_status, which hands Claude the link to your result once the job is done.

No contact data: no emails, no phone numbers, no people's profiles, and no search by person. Firmus answers about companies, from the public register.


What changed, and since when.

timeline answers with the changes the register recorded: a cessation or a reactivation, a rename, a new activity or legal form, a head office that moved, an establishment opened or closed, a workforce band that changed. Each event says when it happened, when Firmus recorded it, and where it came from.

# one event, as timeline answers it
{
  "kind": "legal_entity.head_office_moved",
  "severity": "notable",
  "occurred_on": "2026-05-11",
  "recorded_at": "2026-11-01T08:51:16Z",
  "source": "sirene_daily",
  "bulk": false,
  "subject": { "kind": "legal_entity", "number": "332976976" },
  "payload": {
    "to": {
      "registered_city": "PARIS", "registered_address": "25 RUE D'ASTORG",
      "registered_postal_code": "75008"
    },
    "from": {
      "registered_city": "MONDEVILLE", "registered_address": "ROUTE DE PARIS",
      "registered_postal_code": "14120"
    }
  }
}

The log is new: it starts no earlier than 2026-10-29, when its daily recording shipped, and nothing older was filled in. A change's own date can be older, when the register reports it late. An empty timeline means nothing has been recorded, not that nothing happened.


The data

The register, counted.

France is the register covered today: INSEE's Sirene.

43 896 818
establishments in the search index
30M
legal entities imported from the register
2026-08-01
the register's monthly publication answering now

Between two monthly publications we apply the register's daily change feed every morning — about 33 000 record changes a weekday — so a company that changed yesterday answers correctly today. On every record and every enriched row, data_updated_at is the date the register last changed it, never the date anything here was rebuilt.


For developers

The same answers, over HTTP.

Each tool is a thin wrapper over one endpoint of the API, and a key from the console calls the endpoint directly. The field below searches the register live, on a shared demo key.

BNP PARIBAS
662 042 449
active
partial falsetook_ms 49
bash
# the same search, from your terminal
curl -H "Authorization: Bearer fk_pub_acilFaSqbqW0a1DjYZZwq1IIDPpWAnj4" \
  'https://api.firmus.sh/v1/fr/suggest?q=bnp+pariba&limit=5'

The whole API, 19 endpoints

# only fr is indexed today
GET /v1/{country_code}/legal-entities/{registry_number}
GET /v1/{country_code}/legal-entities/{registry_number}/establishments
GET /v1/{country_code}/legal-entities/{registry_number}/events
GET /v1/{country_code}/establishments/{establishment_number}
GET /v1/{country_code}/suggest?q=
POST /v1/{country_code}/resolve
POST /v1/{country_code}/enrich
GET,POST /v1/{country_code}/watchlists
GET,PATCH,DELETE /v1/{country_code}/watchlists/{id}
GET,POST,DELETE /v1/{country_code}/watchlists/{watchlist_id}/watches
GET /v1/{country_code}/watchlists/{watchlist_id}/segments
PUT,DELETE /v1/{country_code}/watchlists/{watchlist_id}/segments/{segment_id}
GET /v1/{country_code}/events?cursor=
GET,POST /v1/{country_code}/segments
GET,DELETE /v1/{country_code}/segments/{id}
POST /v1/{country_code}/segments/{id}/export
POST /v1/{country_code}/jobs
GET /v1/{country_code}/jobs/{id}
GET /v1/{country_code}/jobs/{id}/result

A contract that holds still.

json
# the legal record behind a pick, trimmed
curl -H "Authorization: Bearer fk_pub_acilFaSqbqW0a1DjYZZwq1IIDPpWAnj4" \
  'https://api.firmus.sh/v1/fr/legal-entities/552032534'

{
  "country_code": "fr",
  "registry_number": "552032534",
  "kind": "company",
  "name": "DANONE",
  "legal_form": { "code": "5599", "scheme": "insee_cj_2018" },
  "activity": { "code": "70.10Z", "scheme": "naf2008" },
  "workforce": { "range_code": "42", "scheme": "insee_tranche_effectifs", "year": 2023 },
  "size_category": { "code": "GE", "scheme": "insee_categorie_entreprise", "year": 2023 },
  "status": "active",
  "registered_on": "1955-01-01",
  "ceased_on": null,
  "registered_address": {
    "line": "59 RUE LA FAYETTE", "postal_code": "75009", "city": "PARIS"
  },
  "partially_disclosed": false,
  "data_updated_at": "2026-04-10T11:28:37Z",
  "country_data": { "sigle": null, "economie_sociale_solidaire": false, "unite_purgee": false, … }
}

Pricing

A flat fee, with the rows included.

Every plan includes a number of rows a month that resolve and enrich look up, counted together: a row that could not be matched is still a row looked up, and a file resolved and then enriched spends its matched rows twice. Once they are spent both refuse until the month ends, and nothing is billed per row.

Free

To run a first file and see what comes back.

€0
  • 1 000 rows a month looked up by resolve and enrich, counted together
  • 1 000 API calls a month — every request counts, tool calls from Claude included; checking on a file job is free
  • 2 requests per second
  • 5 companies or establishments watched at once, across all your lists
  • Segments by filter: 3 saved at once, 1 watched for companies that enter them, 1 000 rows exported a month
  • 1 API key
  • Publishable key for the browser, 100 calls a day per calling address, then refused
  • Documentation, and no support queue
Start free
ProMost teams

For a team that enriches its exports every month.

€49/mo
  • 25 000 rows a month looked up by resolve and enrich, counted together
  • Unlimited company lookups, 15 requests per second across the account
  • 1 000 companies or establishments watched at once, across all your lists
  • Segments by filter: 100 saved at once, 10 watched for companies that enter them, 25 000 rows exported a month
  • Publishable key for the browser, 100 calls a day per calling address, then served within the plan's rate
  • plannedCompliance pack
  • Email support, 2 business days
Create an account
Scale

For large files, and for an integration of your own.

€249/mo
  • 250 000 rows a month looked up by resolve and enrich, counted together
  • Unlimited company lookups, 60 requests per second across the account
  • 10 000 companies or establishments watched at once, across all your lists
  • Segments by filter: 1 000 saved at once, 100 watched for companies that enter them, 250 000 rows exported a month
  • Publishable key for the browser, 100 calls a day per calling address, then served within the plan's rate
  • plannedCompliance pack
  • Email support, 1 business day
Create an account

A paid plan is a flat monthly fee, collected in advance. No credits, and nothing billed per row or per call, on any plan.

20% off on annual prepay.

The free tier is permanent and takes no card.

Segments are built from INSEE's Sirene register. They do not reflect an opposition to prospecting recorded only in the RNE, the national business register, which Firmus does not read yet. Companies whose entry is partially disclosed are counted, never listed.

More than 60 requests per second or 250 000 rows a month, or an invoice instead of a card? Write to us.