Skip to content
firmus.shdocs

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

Enrich

Add chosen columns to up to 500 identified companies, each value with its source and date.

A row is either a registry_number (SIREN) with an optional ref, or a row of a resolve answer sent back exactly as you received it. A matched resolve row is enriched with its company; an ambiguous, not_found or invalid one comes back with its own status and a message, since there is no single company behind it. Any other column on a SIREN row, siren for instance, makes the row invalid.

fields chooses the columns for the whole batch. Name a field, or a theme to get all of its fields:

ThemeFields
identityname, legal_form, registered_on, status, ceased_on
activityactivity
sizeworkforce, size_category
head_officehead_office_address, head_office_coordinates
establishmentsactive_establishments
eventsevents
legalcollective_proceeding, last_accounts_filed, last_business_transfer

Without fields you get name, status, activity, workforce and head_office_address. The answer's top-level fields lists what every row carries. Codes come with their INSEE label, in French; activity also carries its scheme, and its label is null unless the scheme is naf2008. events is the latest event of each kind you list in event_kinds, newest first, each with occurred_on, source and bulk. When you leave event_kinds out it is every legal_entity.* kind of the timeline but filed accounts (legal_entity.accounts_filed and its corrections), which you get by naming them. Establishment event kinds are not available here. A bulk event is returned, with bulk: true. events is the raw log, as the timeline is: a correction or a cancellation is a kind of its own and is not applied, so a legal_entity.insolvency.opened can be there beside the legal_entity.insolvency.opened.cancelled that withdrew it, on a row whose collective_proceeding says open: false. Only the legal fields below apply corrections.

The legal fields are read from the notices of the BODACC, France's legal gazette, with the gazette's history included, bulk or not, and corrections applied: a cancellation withdraws the notice it names, a correction replaces it, and a court's retraction of an opening, which names no notice, withdraws the company's latest opening before it.

  • collective_proceeding is an object on every row read in full. open says whether an insolvency proceeding is open; procedure is safeguard, accelerated_safeguard, reorganisation, liquidation or crisis_exit; stage is where the last judgment left it, opened, plan or closed. A company under an adopted plan has stage: plan and open: true, since the proceeding goes on under it. A liquidation closed and then resumed is the same proceeding opened again: stage: opened, with its first opened_on. opened_on is the date the proceeding opened, and can be null while open is true when the gazette gave no opening this API could read; updated_on and notice_url are the date and the notice of the last judgment. With no insolvency notice, open is false and the rest null.
  • last_accounts_filed is the latest filing of accounts: published_on, the bulletin's date, and closing_on, the last day of the fiscal year filed. Not the figures. null when none is recorded.
  • last_business_transfer is the latest sale of a business the company was party to: direction (sold or acquired), occurred_on, and counterparties, the other party's registry numbers. null when none is recorded.

Each carries source: "bodacc" and a notice_url, the notice to cite. A notice about a company that was partially disclosed in the registry, or that the registry did not hold yet, when the notice was read is recorded without its values, and stays so: the dates and open still count, but procedure, closing_on, counterparties or notice_url can be null on a row whose partially_disclosed is false. The BODACC covers companies in the trade register only. For an association or a sole trader outside it, open: false and a null means no notice was published, not that there was nothing to publish.

Each enriched row carries a sources object that names the source of each group of fields, null on a row that was not enriched:

{
  "sources": {
    "registry": "insee_sirene",
    "data_updated_at": "2026-09-14T08:30:00Z",
    "head_office_data_updated_at": "2026-09-01T12:00:00Z",
    "legal": { "registry": "bodacc", "published_on": "2026-06-02" }
  }
}
  • registry is insee_sirene, the source of every value but events and the legal fields. data_updated_at is the registry's timestamp for the company's record, not an import time, and head_office_data_updated_at that of the head-office establishment's record, which the département and coordinates come from; it is null when no head-office field was selected.
  • legal names the BODACC as the source of the legal fields: registry: "bodacc" and published_on, the bulletin date of the latest notice behind the legal fields you selected. published_on is null when no notice is behind them — or only notices recorded without their values, as above — and legal itself is null when you selected no legal field. On a row with partial: true, a null published_on can also mean the legal fields were not read in time: send the row again before you conclude there is no notice.
  • Each event carries its own source and occurred_on, and each legal fact its source, dates and notice_url.

When you republish these values, give each group its source and date — Sirene with data_updated_at, the BODACC with published_on — rather than the time of your call.

A company whose registry record is partially disclosed comes back with partially_disclosed: true, and the masked values are null: its name and street address (postal_code and city survive), the head office's département and coordinates, and the rename and head-office-move events are left out of events. When only the head office is partially disclosed, its département and coordinates and those two events are withheld the same way, and the row also says partially_disclosed: true when the head office was read, that is when you selected a head-office field or events. The flag says whether something on this row is masked, so a null on a true row may be withheld by law rather than absent; the full card's partially_disclosed describes the company alone. The legal fields follow the company's status only: those of a partially disclosed company keep open, stage, direction and their dates, and lose procedure, closing_on, counterparties and notice_url, which are null, while a disclosed company whose head office is masked keeps them. A ceased company is enriched, with status: ceased. A valid SIREN the registry does not hold is not_found.

A batch spends at most 10 seconds reading. A row the budget did not reach comes back not_processed, with partial: true and a message; it is never reported as not_found. A row read only in part comes back enriched with partial: true, and the parts not read are null. Send either kind of row again. The batch is refused with 400 invalid_request only when it is not a batch (not JSON, no rows array, an empty one, more than 500 rows), when fields or event_kinds is empty or names something outside the lists above, or when event_kinds is sent without events in fields. A country other than fr is a 404. One batch runs at a time per organization, resolve and enrich together, and each server answers one at a time: a second one gets 429 concurrency_limited, even when batches are sent one after another. Retry after the Retry-After seconds the response gives, which differ between the two cases: do not hard-code them. For a file larger than one batch, submit a file job instead.

A batch is one call, however many rows it holds: on Free, one of the month's 1 000 lookups. Its rows are counted separately, on every plan, against the month's agent rows, shared with resolve: 1 000 on Free, 25 000 on Pro, 250 000 on Scale. Each row enriched or not_found is one row, and a SIREN repeated in a batch counts each time. invalid rows, resolve rows passed through (a resolve not_found included), and not_processed or partial rows are not counted. The rows your unfinished file jobs hold count as used. As on resolve, a batch admitted with rows left can take you past the allowance by up to its own size, and the next batch is refused with 402 quota_exceeded until the start of the next calendar month, UTC. Call it from a server with a secret key holding the read scope; a publishable fk_pub key is refused with 403 public_key_forbidden when it holds read, and with 403 insufficient_scope when it does not. Authentication covers both.

POST/v1/{country_code}/enrichScope read

Parameters

ParameterInTypeRequiredExample
country_codepathstringYesfr

Request

bash
curl -X POST -H "Authorization: Bearer $FIRMUS_KEY" \
  "https://api.firmus.sh/v1/fr/enrich"

Fields

  • fieldsstring[]
    • []stringoptional
  • resultsobject[]
    • []objectoptional
      • refstringnullable
      • statusstring
      • registry_numberstringnullable
      • partially_disclosedbooleannullable
      • dataobjectnullable
        • namestringoptionalnullable
        • statusstringoptional
        • activityobjectoptional
          • codestringnullable
          • schemestringnullable
          • labelstringnullable
        • workforceobjectoptional
          • codestringnullable
          • labelstringnullable
          • yearintegernullable
        • head_office_addressobjectoptional
          • addressstringnullable
          • postal_codestringnullable
          • citystringnullable
          • departementstringnullable
        • legal_formobjectoptional
          • codestringnullable
          • labelstringnullable
        • registered_onstringoptionalnullable
        • ceased_onstringoptionalnullable
        • size_categoryobjectoptional
          • codestringnullable
          • labelstringnullable
          • yearintegernullable
        • head_office_coordinatesobjectoptionalnullable
          • latitudenumber (float)
          • longitudenumber (float)
        • active_establishmentsintegeroptionalnullable
        • eventsobject[]optionalnullable
          • []objectoptional
            • kindstring
            • occurred_onstring
            • sourcestring
            • bulkboolean
        • collective_proceedingobjectoptionalnullable
          • openboolean
          • procedurestringnullable
          • stagestringnullable
          • opened_onstringnullable
          • updated_onstringnullable
          • sourcestring
          • notice_urlstringnullable
        • last_accounts_filedobjectoptionalnullable
          • published_onstring
          • closing_onstringnullable
          • sourcestring
          • notice_urlstringnullable
        • last_business_transferobjectoptionalnullable
          • directionstring
          • occurred_onstring
          • counterpartiesstring[]nullable
            • []stringoptional
          • sourcestring
          • notice_urlstringnullable
      • sourcesobjectnullable
        • registrystring
        • data_updated_atstringnullable
        • head_office_data_updated_atstringnullable
        • legalobjectnullable
          • registrystring
          • published_onstringnullable
      • partialboolean
      • messagestringnullable
  • countsobject
    • enrichedinteger
    • ambiguousinteger
    • not_foundinteger
    • invalidinteger
    • not_processedintegeroptional

Responses

Adds the selected fields to each row of a batch of up to 500 identified companies. A row is a `registry_number` (SIREN), or a row of a /resolve answer sent on as it came: a `matched` row is enriched by its company, and any other status comes back as it is. `ref` is echoed. `fields` selects what each row carries, from a closed list grouped by theme — identity (`name`, `legal_form`, `registered_on`, `status`, `ceased_on`), activity (`activity`), size (`workforce`, `size_category`), head_office (`head_office_address`, `head_office_coordinates`), establishments (`active_establishments`), `events`, and legal (`collective_proceeding`, `last_accounts_filed`, `last_business_transfer`) — a theme's name selecting all of its fields. Without it: `name`, `status`, `activity`, `workforce`, `head_office_address`. `events` is the latest event of each kind in `event_kinds` (every legal-entity kind but filed accounts by default), each with its date and source. The legal fields are read from the BODACC legal gazette's events, corrections and cancellations applied, each with its `source`, its date and the link to its notice; the BODACC covers companies in the trade register only. `sources` names the source of each field group: INSEE Sirene (`registry`) for every value but the events and the legal fields, with the date it last changed the record, and the BODACC (`legal`) for the legal fields, with the publication date of the latest notice behind them. Nothing partial disclosure masks is returned: the row says `partially_disclosed`. A batch reads for at most 10 seconds: a row it did not reach is `not_processed` (never a `not_found`), and one it read only in part is `partial`; send either again. The batch is one call; each row enriched or not found is one agent row against the plan's monthly allowance, shared with resolve (Free 1 000, Pro 25 000, Scale 250 000), refused with 402 `quota_exceeded` once spent; invalid rows, rows passed through from resolve (whatever their status) and `not_processed` or `partial` rows are not counted. One batch runs at a time per organization and per server, resolve and enrich together: a second one is answered 429 `concurrency_limited` with Retry-After. A publishable (fk_pub) key is refused with 403 `public_key_forbidden`.

{
  "fields": [
    "name",
    "legal_form",
    "registered_on",
    "status",
    "ceased_on",
    "activity",
    "workforce",
    "size_category",
    "head_office_address",
    "head_office_coordinates",
    "active_establishments",
    "events",
    "collective_proceeding",
    "last_accounts_filed",
    "last_business_transfer"
  ],
  "results": [
    {
      "ref": "crm-1",
      "status": "enriched",
      "registry_number": "552032534",
      "partially_disclosed": false,
      "data": {
        "name": "DANONE",
        "legal_form": {
          "code": "5599",
          "label": "SA à conseil d'administration (s.a.i.)"
        },
        "registered_on": "1955-01-01",
        "status": "active",
        "ceased_on": null,
        "activity": {
          "code": "70.10Z",
          "scheme": "naf2008",
          "label": "Activités des sièges sociaux"
        },
        "workforce": {
          "code": "41",
          "label": "500 à 999 salariés",
          "year": 2023
        },
        "size_category": {
          "code": "GE",
          "label": "Grande entreprise",
          "year": 2023
        },
        "head_office_address": {
          "address": "17 BD HAUSSMANN",
          "postal_code": "75009",
          "city": "PARIS",
          "departement": "75"
        },
        "head_office_coordinates": {
          "latitude": 48.873,
          "longitude": 2.331
        },
        "active_establishments": 2,
        "events": [
          {
            "kind": "legal_entity.head_office_moved",
            "occurred_on": "2026-09-03",
            "source": "sirene_daily",
            "bulk": false
          }
        ],
        "collective_proceeding": {
          "open": false,
          "procedure": null,
          "stage": null,
          "opened_on": null,
          "updated_on": null,
          "source": "bodacc",
          "notice_url": null
        },
        "last_accounts_filed": {
          "published_on": "2026-06-02",
          "closing_on": "2025-12-31",
          "source": "bodacc",
          "notice_url": "https://www.bodacc.fr/pages/annonces-commerciales-detail/?q.id=id:C202600000001"
        },
        "last_business_transfer": null
      },
      "sources": {
        "registry": "insee_sirene",
        "data_updated_at": "2026-09-14T08:30:00Z",
        "head_office_data_updated_at": "2026-09-01T12:00:00Z",
        "legal": {
          "registry": "bodacc",
          "published_on": "2026-06-02"
        }
      },
      "partial": false,
      "message": null
    },
    {
      "ref": "crm-2",
      "status": "ambiguous",
      "registry_number": null,
      "partially_disclosed": null,
      "data": null,
      "sources": null,
      "partial": false,
      "message": "Resolve did not match this row to one company: there is nothing to enrich."
    }
  ],
  "counts": {
    "enriched": 1,
    "ambiguous": 1,
    "not_found": 0,
    "invalid": 0,
    "not_processed": 0
  }
}