Skip to content
firmus.shdocs

Every page's text, headings and title. Code samples are not indexed.

Use Firmus from Claude

Add Firmus to Claude as a connector, sign in, and enrich a CRM export, follow a supplier's changes or identify a messy list of French companies in plain language.

Firmus is also a remote MCP (Model Context Protocol) server: a connector you add to Claude once. Claude can then identify the French companies in a file you attach or a list you paste, add registry columns to them, hand the whole file back as a CSV, fetch the record of one company, list what changed about it, watch it and read what happens to it next, or count the companies matching a description, export them, and be told which new ones match it later. You write no code. Every answer says where it comes from and when: a company record or an enriched row carries the date the registry last changed it, and an event the date it happened, so Claude can cite its sources rather than assert.

Firmus is company data from the French national registry, INSEE Sirene, and nothing else. It holds no contact data — no email addresses, no phone numbers, no named people — and no officers or shareholders, so it cannot search by person: "every company this person runs" has no answer here.

The server lives at:

https://api.firmus.sh/mcp

Add the connector

  1. In Claude's connector settings, add a custom connector.
  2. Name it Firmus and give https://api.firmus.sh/mcp as its URL. If Claude offers fields for an OAuth client ID and secret, leave them empty: Claude registers itself with Firmus when it connects.
  3. Connect. Claude opens a Firmus page in your browser.

Sign in and allow access

  1. Sign in to the Firmus console with your email address and password, or choose Create an account (a password of at least 12 characters; the organization is named after your email domain). Either way you come back to the next screen.
  2. The screen is titled Connect followed by the app's name, and shows three facts:
    • Returns to: the host your browser is sent back to. It should be Claude's.
    • Identity: either Published at a host, or "Registered itself. Firmus has not verified the name; check the host it returns to." In the second case, Returns to is the line to trust.
    • Access: read, "Look up legal entities and establishments", and, when the app asks for it, suggest, "Search companies by name or identifier".
  3. Under Acts for, pick the organization whose plan the calls count against. Choose Allow access, and the browser returns to Claude. Deny returns to Claude with nothing granted.

Claude is now connected. If the screen says "This request has expired or has already been answered", go back to Claude and connect again. If it says the account "is not a member of an organization", there is nothing to connect Claude to yet: sign in with an account that belongs to one.

To end the access, open Connected apps in the console, choose Disconnect on the connection, and confirm: Claude's access stops working within a second. Removing the connector in Claude only stops Claude from using it; the console is where the access is revoked on the Firmus side.

Enrich a CRM export

Attach the CSV export, then ask:

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

What Claude does depends on the file's size:

  • Up to 500 rows: resolve to identify each row, then enrich with what resolve returned, one call after the other. The answer arrives in the conversation.
  • A whole file, or more than 500 rows: submit_job with the file's content, which answers with a job id, then job_status until the job has finished. Claude then gives you a download link.

submit_job finds the name, postal code, city, address, SIREN, SIRET and VAT number columns from the headers, and says which it used: if it picked the wrong one, tell Claude which column to use instead. Every other column is carried through untouched.

The file you download is yours, every row and column kept, with Firmus's columns appended, all prefixed firmus_: firmus_resolve_status, firmus_resolve_confidence and firmus_registry_number for the identification, firmus_candidates on a row with more than one possible company, then firmus_enrich_status, the columns you asked for, and firmus_data_updated_at, the date the registry last changed that company's record. Without a choice of columns, enrich adds name, status, activity, workforce band and head office address. Then comes firmus_partial, true on a row whose search ran out of time even after the job tried it again: its not_found or ambiguous is not a verdict. Claude reports how many such rows the job holds; ask it to submit them again. The last two columns are firmus_partially_disclosed, true when something on the row is withheld from public reuse, so an empty name or address is withheld by law rather than missing, and firmus_sources, the registries the row's values come from: insee_sirene, followed by bodacc and the date of the latest notice when you asked for a legal field. Quote those two when you pass the file on.

The labels for legal form, activity, workforce band and size category are the registry's own, in French: Activités des sièges sociaux, not "Activities of head offices". Ask Claude to translate them if your file needs English.

The link opens without signing in, for anyone holding it, until the job is deleted seven days after submission: share it as you would the file. If a job failed partway, the file holds the rows answered before it stopped, and the job's error says how many: ask Claude to submit the rest. Claude sends the file to Firmus as text inside its own call, so a very large export can be too long for Claude to send in one piece even when your plan allows it. Split it, or have a developer upload it as a file job.

What changed for this supplier since June

What has changed for our supplier Danone since June 2026? Cite each change with its date.

Claude calls resolve to find the SIREN behind the name (or skips it if you give the SIREN), then timeline with occurred_from set to 2026-06-01. The answer lists the events newest first, ten at a time unless you ask for more: a cessation, a rename, a change of activity, legal form or workforce band, a head office or an establishment that moved, opened or closed. Each event carries the date it happened (occurred_on), the date Firmus recorded it (recorded_at) and its source, and for a change of value what it was and what it became.

The registry's part of the log is young, and an empty or short answer usually means that. It starts no earlier than 29 October 2026, the day the event log began recording: nothing the registry processed before then is in it, and no earlier registry history is filled in. The gazette's notices, below, go back to January 2008. A change effective in June that the registry processed after that date does appear, under its June date. So "nothing since June" means nothing was recorded since the log began, not that nothing happened. To tell the two apart, ask Claude to look the company up: its record carries the date the registry last changed it. If that date is after June and the timeline is empty, the record changed in a way the timeline does not show — before the log began, or in a field it does not track — and the record gives the current values but not the previous ones.

Two more things shape the answer:

  • Once a month, Firmus records late the changes its daily updates missed, and some days the registry changes a large part of itself at once. Both are left out unless you ask for them: add "include the monthly corrections and mass operations" to the question.
  • The events come from INSEE Sirene and from the BODACC legal gazette: insolvency proceedings, sales of a business, removals from the trade register and other legal notices. The gazette's notices since 2008 were loaded at once and count as a mass operation, so "has this supplier ever been in insolvency" needs the phrase above. The BODACC covers companies in the trade register only: for an association or a sole trader outside it, an empty timeline says nothing about proceedings.

A company that has left the registry still has its timeline: Claude is told it is no longer in the registry, lookup no longer finds it, and its events keep their kinds and dates but not their values. Its removal is one of the monthly corrections, so ask for those to see it.

An event about a company or establishment that is partially disclosed today — the person behind it asked for parts of the record to be withheld from public reuse — keeps its kind and dates but not the values that changed. The full list of event kinds is in list events.

Identify a messy list

Paste the list as you have it — names, cities, typos and all — and ask:

Find the SIREN of each of these companies. Give me the confidence for each, and list separately the ones you could not match with certainty.

danone paris Michelin, Clermont-Ferrand boulangeries paul, lille société générale

Claude calls resolve with one row per line, up to 500 a call. Each row comes back with a status:

  • matched: one company, with a confidence between 0 and 1 and the parts of your line the match rests on. A typo or a missing word lowers the confidence, and can leave the row ambiguous.
  • ambiguous: no safe answer. Up to three candidates come back, each with its own confidence, and Claude is told to show them to you rather than pick one. A name with no city or postal code — the last line above — is never matched however exact it is: give the city, and ask again.
  • not_found: no company close enough. Below Firmus's threshold the answer is a refusal, not a guess.
  • invalid: the row could not be read, with a message saying why.

A ceased company is matched and marked ceased: a list often holds companies that have since closed, and saying so is the answer. A batch spends at most 10 seconds searching names; a row it did not reach comes back not_found and marked partial, is not counted, and Claude is told to send it again. Each matched company comes back as a short card — SIREN, name, head office city, activity code, status — and Claude calls lookup for its dated record. How matching works is in the resolve reference.

Watch companies and hear what happens to them

Watch our three biggest suppliers, 552032534, 552081317 and 542051180, and tell me what has happened to them since we last talked.

Claude calls watch with the numbers, then watched_events. Without a list named, the numbers go to the organization's watchlist "Watched from an assistant", created the first time. Each number comes back added, already_watched, not_found — unknown to the registry, so not watched — or invalid, with how many of the plan's watched companies are used. Watching starts then: for what happened before, ask for the company's timeline.

watched_events reads the events of every watched company, oldest first, ten at a time unless you ask for more, each with its date and source. It answers with a cursor: Claude can keep it and pass it next time, so "since we last talked" reads only what is new. An item marked retyped is a legal notice first recorded without its details and now readable; it replaces the earlier one of the same kind and date. An event about a company that is partially disclosed today keeps its kind and dates but not its values.

The same lists also deliver by webhook and email digest, set up in the console; watch companies explains both.

Count companies, and export them

How many IT services companies with at least 10 employees have their head office in the Rhône? Show me how they split by size, then export them all.

Claude turns the question into explicit filters and calls segment: here NAF division 62, département 69, workforce band 11 and up. It answers with the exact count, how it splits by département, activity, workforce band and legal form, and at most ten companies, each with its source and dates — never more in the conversation. The answer says back how each filter was read, so check it: "IT services" read as the whole division 62 is not the same count as 62.02A alone. Ask Claude to change a filter and run it again.

Claude never lists a company that is partially disclosed, and lists sole traders, who are natural persons, only if you ask for them and agree to an acknowledgement it shows you: your organization is the controller of any prospecting of them, informs each of them under article 14 of the GDPR and honours their opposition. Every answer also carries a notice: the counts are built from INSEE Sirene and do not reflect an opposition to prospecting recorded only in the RNE. Claude is told to repeat it when it shows companies.

To export, Claude saves the segment and calls segment_export, which writes every company it may list to a CSV in the background; job_status then gives the download link, as for any file. The file opens on a few lines starting with # — the RNE notice, the segment and its filters, and any acknowledgement — before its header. What the filters accept is in run a segment.

Be told which companies enter a segment

Tell me every time a new IT services company in the Rhône with 10 employees or more shows up, and when one drops out.

Claude saves the segment if it is not saved yet, then calls watch_segment, with include_leavers for the companies that drop out. Without a list named, the segment is followed by the same "Watched from an assistant" list watch uses. Nothing is reported for the companies already in the segment: following starts then, and the first ones arrive after the next daily update of the segment index. Ask for an export if you want today's.

They arrive in watched_events, beside the events of watched companies, as companies that entered or left the segment, each with the date of the index update that showed it, its record as a sample shows it, and the RNE notice, which Claude is told to repeat. A company that is partially disclosed, or a sole trader in a segment saved without the acknowledgement, never appears. If the segment's daily update fails three times in a row, it is paused and nothing arrives; asking Claude to follow it again resumes it, from that moment on. unwatch_segment stops; the segment stays saved. The same companies reach the list's webhooks and digest, set up in the console.

Limits, and what is counted

Calls Claude makes count against the organization you chose at Acts for, exactly as calls made with one of its API keys: the same plan, the same allowances. The plan is a flat monthly fee: nothing is charged per row, and a spent allowance is a refusal, never an extra invoice.

FreeProScale
Agent rows a month, resolve and enrich together1 00025 000250 000
Rows per resolve or enrich call500500500
Rows per file job1 00025 000100 000
Size of a file job2 MB20 MB50 MB
Lookups a month: each lookup, timeline, batch and job1 000unlimitedunlimited
Requests per second, for the whole organization21560
Watched companies, across every watchlist51 00010 000
Saved segments31001 000
Watched segments, across every watchlist110100
Exported rows a month, segment_export1 00025 000250 000

What spends agent rows. Each row resolve looks up and each row enrich enriches or finds missing from the registry is one row; the month runs on the calendar, UTC. Resolving a 500-row list and then enriching it spends at most 1 000. A file job is checked before it starts, for every row once per step — 2 000 for a 1 000-row file resolved then enriched — and is refused if that does not fit in what is left; until it finishes, those rows count as spent, so a resolve or enrich call can be refused while a job runs. A single call is admitted while one row is left, so it can take you past the figure by up to its own 500.

What is not counted. A row that cannot be read, a row the 10-second budget did not reach, and a row resolve could not match that then passes through enrich. Polling job_status and downloading the result are not lookups either, though on Free they stop once the month's lookups are spent. The connector's own messages to Firmus — connecting, listing the tools — are not counted against any monthly allowance, though they do count against the requests per second.

When an allowance is spent, resolve, enrich and submit_job are refused with 402 quota_exceeded until the first day of the next month, UTC. On Free, lookup and timeline keep working while the 1 000 lookups last; on Pro and Scale they always do. The console's Usage screen shows the agent rows spent this month. Beyond a plan's rows is the next plan, and beyond Scale's a contract.

Watched companies are a stock, not a monthly volume. watch and unwatch count against no monthly allowance; watched_events is one lookup per page. A watch that would take the organization past its watched companies adds none of the numbers and is refused with 402 quota_exceeded, with no wait: it frees up when numbers are unwatched, not when the month turns.

Segments. Each segment call is one lookup, like lookup; segment_export is one, or two when it saves the segment first. Saved segments are a stock, like watched companies: a save past the plan's figure is refused with no wait, and deleting a saved segment, from your own integration, frees its place. Exported rows are a monthly volume of their own, not agent rows: an export is checked before it starts for every company the segment may list, refused whole with 402 quota_exceeded if that does not fit in what is left, and counts only the rows it writes. Watched segments are a stock too: watch_segment and unwatch_segment count against no monthly allowance, and following one segment more than the plan's figure is refused with 402 quota_exceeded, with no wait, until unwatch_segment frees one.

One resolve or enrich call runs at a time per organization. A second one — from Claude, or from your own integration using the organization's API keys — is refused with 429 concurrency_limited and a number of seconds to wait. A file job is never refused that way. If your production code calls these endpoints, connect Claude to a separate organization, or expect those waits. Going over the requests per second is 429 rate_limited, also with a wait.

When a call is refused for any of these reasons, or because a company does not exist, Claude receives the refusal's code, its message and the seconds to wait when there are any, rather than an empty answer, and can tell you which it was. The headers and counters behind every figure in the table are in rate limits.

The thirteen tools

ToolWhat it does
resolveIdentifies the French company behind each row of messy data — a name with a city or postal code, a street address, a VAT number, a SIREN or a SIRET — up to 500 rows per call. A row with no safe answer is reported as ambiguous or not found, not guessed.
enrichAdds chosen columns to the companies resolve matched, or to a list of SIRENs, up to 500 rows per call. Unless asked for more: name, status, activity, workforce band and head office address. On request: legal form, creation and cessation dates, size category, head office coordinates, the number of active establishments, the latest event of each kind, and from the BODACC legal gazette whether an insolvency proceeding is open, the last accounts filed and the last sale of a business. Each row names its sources: INSEE Sirene, with the date the registry last changed the record, and, when a legal field is asked for, the BODACC, with the publication date of the latest notice; each legal fact carries its own date and the link to its notice.
lookupFetches one company by SIREN, or one establishment by SIRET: a compact card with its status, legal form code, activity code, workforce band, dates and address, plus the date the registry last changed the record.
timelineLists what changed about one company and its establishments, newest first, 10 events per page by default: from the registry, and from the BODACC (insolvency proceedings, sales of a business, removals from the trade register, registrations, other legal notices, their corrections), each BODACC event with the link to its notice. Filters by kind, severity and dates. Filed accounts are left out unless asked for by kind; monthly corrections and the BODACC's history since 2008 are left out unless asked for. An empty list means the log holds nothing for that company, not that nothing ever happened to it; a company that left the registry is said to be removed, its values withheld; a SIREN neither the registry nor the log knows is a not-found error.
submit_jobSends a whole file to be resolved, enriched, or both, in the background, and answers with a job id rather than the rows. Detects the columns from the headers and says which it used.
job_statusReads a job: its status, the rows processed, how many rows were matched, ambiguous or not found, and how many are not conclusive because their search ran out of time. Once the job has finished, it carries the download link of the result CSV.
watchFollows up to 1 000 SIRENs or SIRETs in a watchlist, by default the organization's "Watched from an assistant". Each number answers added, already watched, not found or invalid, with the watched companies used and included; a request past the allowance adds nothing and is refused. Counts against no monthly allowance.
unwatchStops following up to 100 numbers, from the same list by default. Each answers removed, not watched or invalid; the allowance is freed at once. Counts against no monthly allowance.
watched_eventsReads the events of every watched company, and the companies that entered or left a watched segment, oldest first, 10 per page by default, with a cursor to pass back for what arrives next. Filters by watchlist. One lookup per page.
segmentCounts the active French companies matching explicit filters — activity, département, commune, postal code, workforce band, size, legal form, registration date, a recent head office move or workforce rise, an open insolvency proceeding — with four facets and at most ten companies, each with its source and dates. Says back how each filter was read. Saves the segment on request, and runs a saved one again. One lookup per call.
segment_exportWrites every company of a segment that may be listed to a CSV, in the background, from a saved segment or from filters it saves first, and answers with a job id for job_status. Never writes a partially disclosed unit; sole traders only for a segment saved with their acknowledgement. Counts the rows written against the month's exported rows.
watch_segmentFollows a saved segment from a watchlist, by default "Watched from an assistant": the companies that newly match it, and on request those that stop matching, arrive in watched_events from the next daily update of the index, never those already in it. Never delivers a partially disclosed company; sole traders only for a segment saved with their acknowledgement. A follow past the plan's watched segments is refused. Counts against no monthly allowance.
unwatch_segmentStops a watchlist following a segment, from the same list by default. The segment stays saved; its place in the watched segments is freed once no list follows it. Counts against no monthly allowance.

On enrich and lookup, values a company has had withheld from public reuse come back empty, and partially_disclosed: true says so. The fields, themes and event kinds enrich accepts are listed in the enrich reference.

From another MCP client

Any client that speaks Streamable HTTP can connect to the same URL. A client that supports OAuth signs in as above. One that does not can send an API key from the console instead, as a header — a key with the read scope, never in the query string:

Authorization: Bearer fk_live_…

A request without a valid credential is answered 401, with a WWW-Authenticate header pointing at https://api.firmus.sh/.well-known/oauth-protected-resource/mcp, which is how an OAuth client finds where to sign in. See authentication for keys and scopes.