# Is this SIREN a real, still-active company? INSEE Sirene > An agent holding a SIREN or SIRET gets the official INSEE Sirene identity card in one paid call — legal name, active or ceased status, head office, no account. Published 2026-08-11 · Updated 2026-08-16 · HTML version: https://invoket.com/blog/is-this-siren-a-real-still-active-company --- An agent about to onboard a supplier, book an inbound invoice or release a first payment holds a nine-digit number it did not verify. `394406938` is a well-formed SIREN. So is `394406939` — it just isn't one. [`GET /company/resolve`](/docs/api/company-resolve) turns that number into the official identity card: legal name, **active or ceased** status, legal form, NAF activity, workforce band, creation date and head-office address, served offline from the **INSEE Sirene** register under the Etalab open licence. One call, no account, no API key. The three things worth knowing before wiring it are that **a ceased company is a paid answer**, that a **SIRET resolves to its legal unit** and says so, and that a field the register does not carry comes back `null` **with a receipt** rather than filled in from somewhere else. Below, each is walked with responses captured from production on 11 August 2026, against the Sirene snapshot dated **2026-07-31**. ## The identity card, captured `GET /company/resolve?siren=542051180`: ```json { "data": { "siren": "542051180", "name": "TOTALENERGIES SE", "acronym": null, "natural_person": null, "status": "active", "legal_form": { "code": "5800", "label": "Société européenne" }, "main_activity": { "code": "70.10Z", "label": "Activités des sièges sociaux", "nomenclature": "NAFRev2" }, "workforce": { "bracket": "51", "year": 2023 }, "created_on": "1954-01-01", "last_processed_on": "2025-12-06", "is_employer": null, "social_economy": false, "headquarters": { "siret": "54205118000066", "status": "active", "address": { "line": "2 PLACE JEAN MILLIER", "postal_code": "92400", "city": "COURBEVOIE", "country": null }, "created_on": "2000-03-22" }, "lei": { "lei": "529900S21EQ1BO4ESM68", "legal_name": "TotalEnergies SE", "entity_status": "ACTIVE", "registration_status": "ISSUED", "verified_against_sirene": true, "total_matches": 1 }, "coverage": { "missing": [] } }, "provenance": { "source": "insee-sirene", "fetched_at": "2026-08-11T15:21:50Z", "freshness": { "kind": "snapshot", "as_of": "2026-07-31T00:00:00Z" } } } ``` The lookup runs against a local store, so there is **no network call and no secret** at request time — the same property that makes [`/iban/resolve`](/docs/api/iban-resolve) and [`/phone/validate`](/docs/api/phone-validate) answer in milliseconds. The key is a **SIREN or a SIRET, never a name**: this endpoint serves agents that already hold an identifier off an invoice, a contract or a supplier form. The `lei` block appears only when an entity in the GLEIF reference declares this SIREN — a bridge to the global identity, and the entry point to [`GET /company/lei`](/docs/api/company-lei). It is absent for most French companies, which is a fact about LEIs, not a gap. Note that the GLEIF `legal_name` sits **beside** the Sirene `name`, never in place of it: two self-declared registers, two spellings, neither rewritten with the other. ## Roughly half of what you can look up has ceased `status: "ceased"` comes back as a **200, and it is billed**. That is the whole point: the agent asked "who is this company and is it still trading?", and "it stopped" is precisely the answer that should halt an onboarding. `GET /company/resolve?siren=552100554` returns `PEUGEOT SA` with `status: "ceased"`, a ceased head office in Vélizy-Villacoublay, and a `lei` block reading `entity_status: "INACTIVE"`, `registration_status: "RETIRED"`. Two registers agreeing that a famous name is no longer a live counterparty. This is not an edge case. Probing random check-digit-valid SIRENs against the served snapshot, **80 of the 169 legal units that resolved came back `ceased`** — the register is a historical record, not a directory of going concerns. An integration that treats "found in Sirene" as "safe to pay" has misread the answer by a factor of two. The register also moves in bulk. INSEE ran a consistency alignment between Sirene and the national business registers on **17–18 June 2026**, updating **over 260,000 legal units** and their establishments, in two successive waves, principally cessations and closures ([Insee, *Sirene Open Data — actualités*](https://www.insee.fr/fr/information/9019311)). A company an agent resolved as active in May could be correctly `ceased` in the July snapshot without anything having "broken". ## A SIRET answers about the legal unit, and admits it The v1 identity is the **legal unit plus its head office**. Hand it a SIRET and three things can happen, each distinguishable without guessing: | Input | Result | |-------|--------| | SIRET of the head office | Normal answer plus `is_headquarters: true` | | SIRET of an existing secondary establishment | Answer about the **parent legal unit**, `is_headquarters: false`, plus `coverage.establishment: "resolved_to_legal_unit"` | | Luhn-valid SIRET whose establishment does not exist | `404 NOT_FOUND`, **not billed** | `GET /company/resolve?siret=54205118000033` — a secondary TotalEnergies establishment — returns the TotalEnergies legal unit with: ```json "is_headquarters": false, "coverage": { "establishment": "resolved_to_legal_unit", "missing": [] } ``` Read that marker before reading the address. The `data` describes the legal unit and **its head office**, not the queried establishment's own record — the v1 store does not carry per-establishment addresses, dates or workforce, and says so rather than quietly serving the head office as though it were the branch on the invoice. The existence check matters more than it looks. A SIRET's five-digit NIC means a typo has roughly a one-in-ten chance of passing the checksum; the existence index is what catches the nine other cases. ## Checksum failure and non-existence are different answers Both leave the 200 range, both are unbilled, and an agent must react to them in opposite ways: ``` GET /company/resolve?siren=394406939 → 400 { "code": "INVALID_CHECKSUM", "error": "siren failed its checksum (Luhn): likely a typo" } GET /company/resolve?siren=000000018 → 404 { "code": "NOT_FOUND", "error": "siren not found in the Sirene register" } ``` The first says *fix your input* — one digit off a real number. The second says *this key is well-formed and the register has never heard of it*, which is the answer for an ERP filler value or a fabricated identifier. Collapsing the two into "lookup failed" throws away the distinction that tells an agent whether to retry or to stop. There is one documented exception, and it is live: SIRETs on the **La Poste prefix `356000000` carry no check-digit control at all**. `35600000000051` fails the standard Luhn test and is nonetheless a real establishment — it resolves `200` to LA POSTE with `resolved_to_legal_unit`. So the checksum is bypassed for that prefix entirely and existence decides alone: `35600000099999` is a `404`, never a `400`. A rule that would reject genuine identifiers is not a rule worth enforcing. ## What the register does not say, it does not invent The Sirene register has real gaps: records under **partial or protected diffusion**, fields simply never filled in. Those are served as `null` and **listed** in `coverage.missing`. A live example, an active sole trader: ```json { "siren": "810678904", "name": null, "natural_person": null, "status": "active", "legal_form": { "code": "1000", "label": "Entrepreneur individuel" }, "main_activity": { "code": "68.20A", "label": "Location de logements", "nomenclature": "NAFRev2" }, "headquarters": { "siret": "81067890400030", "status": "active", "address": { "line": null, "postal_code": null, "city": "PARIS", "country": null } }, "coverage": { "missing": ["name", "headquarters.address"] } } ``` The company exists, it is active, and its name and street address are **withheld by the register** — not missing from the service. An agent reading `coverage.missing` knows the difference between "no data" and "no answer", and can escalate to a human instead of concluding the supplier is fake. In the same sample of 169 units, `headquarters.address` was withheld or unfilled 22 times and `name` 13 times. Labels follow the same discipline. `legal_form.label` and `main_activity.label` come from **embedded INSEE nomenclatures**; a code outside them is served with `label: null`, never an invented wording. That is common on old records: of the 169 sampled, 123 carried an activity code in `NAFRev2`, but 25 were still in `NAF1993`, 10 in `NAFRev1` and 11 in the 1970s-era `NAP` — 46 of them with a `null` label. Which is exactly why `main_activity.nomenclature` is a field and not a footnote. ### Store the nomenclature, because it is about to change From **1 January 2027**, NAF 2025 becomes the reference nomenclature for APE codes, approved by *décret n° 2025-736 du 31 juillet 2025*. INSEE is explicit about the blast radius: at that date **every active legal unit in the Sirene register and its establishments will have a modified APE code** ([Insee, *Vers une nouvelle nomenclature : la NAF 2025*](https://www.insee.fr/fr/information/8181066)). An agent that stored `"70.10Z"` alone has stored something that will silently mean a different thing. An agent that stored `code`, `nomenclature` and `provenance.freshness.as_of` together can still explain, in 2028, what it knew and when. ## Billing and failure modes | Case | Result | |------|--------| | Company found — **including `ceased`** | `200`, billed | | SIRET of a secondary establishment, resolved to its legal unit | `200`, billed | | Fields withheld by the register, listed in `coverage.missing` | `200`, billed | | Both or neither of `siren` / `siret`, malformed identifier | `400 INVALID_INPUT`, **not billed** | | Well-formed identifier failing its Luhn check | `400 INVALID_CHECKSUM`, **not billed** | | Well-formed identifier unknown to the register | `404 NOT_FOUND`, **not billed** | | Store not yet ingested | `503 DATA_UNAVAILABLE`, not settled | The line is the same one the rest of the catalog draws: the agent pays for the **answer to its question**, and an absence of activity is an answer. A key the register has never seen is not — nobody should pay to learn their input was fiction. Freshness is declared, never faked. Answers carry `freshness.kind: "snapshot"` with the end-of-month `as_of` of the Sirene stock that backed them; INSEE publishes a monthly stock file, and a missed refresh means the last good snapshot keeps being served under its honest date. **Stale data is never turned into a 5xx.** ## Wiring it up 1. **Branch on `status` before anything else.** `active` and `ceased` are both `200`s. Only one of them should let a payment through. 2. **Check `coverage` before trusting a null.** `missing` tells you the register withheld a field; `establishment` tells you a SIRET was resolved upward to its legal unit. 3. **Keep `freshness.as_of` with the record.** "On what basis did the agent onboard this supplier in August 2026" is answerable only if the snapshot date was stored beside the verdict. 4. **Treat 400 and 404 as distinct branches.** Retry after fixing the input; stop after a `NOT_FOUND`. 5. **Discover, then pay.** The `402` → pay → replay cycle is walked with runnable snippets in the [Quickstart](/docs/quickstart); the machine discovery surfaces are described in [For agents](/docs/for-agents). Identity is one question among several. The SIREN you just resolved is also the key to [`/company/vat`](/docs/api/company-vat) (is the intra-EU VAT number valid today), [`/company/events`](/docs/api/company-events) (has an insolvency announcement been published), [`/company/peppol`](/docs/api/company-peppol) (can this company actually receive the e-invoice you are about to send — which becomes an operational question for every VAT-registered French business from **1 September 2026**, when receiving structured e-invoices becomes mandatory), and [`/company/ownership`](/docs/api/company-ownership) (who consolidates it). If you would rather buy the whole picture in a single settlement instead of orchestrating the family yourself, [`GET /company/report`](/docs/api/company-report) bundles them by SIREN with provenance per block, and [`/preflight/supplier`](/docs/api/preflight-supplier) turns the bundle into a one-call onboarding verdict. The identity of an issuer read off an inbound invoice starts at [`/invoice/read`](/docs/api/invoice-read). Every amount and every accepted settlement rail lives in the gateway's [`/catalog`](https://api.invoket.com/catalog), which is the single source of truth — **no price appears in this article**. Two limits to keep in view. **There is no search by name**: the key is an identifier, and no fuzzy matching will be added, because a near-match wearing an official register's authority is a guess. And this is **identity, not risk** — no score, no rating, no enrichment from unofficial sources. Naming a counterparty is not screening it; that is [`/screen/entity`](/docs/api/screen-entity) for the name and [`/iban/screen`](/docs/api/iban-screen) for the account. The captures above are **snapshot-dated illustrations**, not a contract: a monthly refresh moves a status, a diffusion request withholds a name, an establishment closes. Only the rules are guaranteed — one key per call, a ceased company served as a ceased company, a withheld field named rather than invented, and an unanswerable request never billed. The full parameter and field contract is on the [`GET /company/resolve` documentation](/docs/api/company-resolve).