GET /company/events
Returns the official BODACC legal announcements for a French company, looked up by SIREN: insolvency proceedings (safeguard, receivership, judicial liquidation), deregistrations, and business sales, as a dated timeline plus factual flags derived mechanically from it. The answer is served from a local store built from the official BODACC gazette published by DILA (history since 2008, 8.5M+ announcements), so a lookup resolves in milliseconds with no network call and no secret at request time.
Use it as the legal-health pre-action check before an agent invoices,
extends credit to, or onboards a French counterparty - “is this company in
liquidation?”, “has it been deregistered?”, “did it just sell its business?”.
It pairs naturally with
GET /company/resolve: resolve answers who the
company is, events answers what has legally happened to it. See the live
/catalog for the authoritative endpoint listing and
price.
x402 golden rule: the agent pays for the answer to its question. A
well-formed SIREN with no announcements at all is a successful answer ->
200 billed, empty list - “no known announcements” is precisely what a
clean counterparty looks like (see the trust
contract below). Requests the service
cannot answer - a malformed SIREN, a failed checksum, an unknown family -
leave the 200 range and are not billed.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
siren | string | yes | 9-digit legal-unit identifier |
family | string | no | Filter the view: insolvency, deregistration or sale (default: all) |
GET /company/events?siren=321875205&family=insolvency
siren is validated in two steps: strict form (9 digits), then the Luhn
check digit (no SIREN is exempt - the La Poste SIREN 356000000 passes the
standard check). A well-formed SIREN that fails its checksum is a
400 INVALID_CHECKSUM, distinct from any “not found”: it is almost certainly
a typo, and the agent should fix the input.
Lookup is by SIREN only: BODACC announcements are published per legal
unit, so there is no SIRET input, and no search by name in v1 - the endpoint
serves agents that already hold an identifier (from an invoice, a contract,
a /company/resolve answer).
The family filter changes what the agent looks at, never the facts:
events, total and truncated describe the filtered view, while the
flags are always derived from the company’s
complete timeline. An unknown family value is a 400 INVALID_INPUT.
200 response - UnifiedResponse
{
"data": { ... },
"provenance": {
"source": "dila-bodacc",
"fetched_at": "2026-07-12T14:50:57Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-12T00:00:00Z" }
}
}
provenance.source:dila-bodacc, the served BODACC store.freshness.kind:snapshot;as_ofis the extraction date of the BODACC dataset that backed the answer.
Fields of data
| Field | Type | Description |
|---|---|---|
siren | string | The queried SIREN, echoed |
company | object | Minimal Sirene identity echo: { name, natural_person { last_name, first_name }, status }; null when the SIREN is unknown to the Sirene register - see coverage.identity |
events | array | Announcements, most recent first, in the view selected by family= |
total | int | Honest count of announcements in the view, before the payload cap |
truncated | bool | true when the view was capped to the 100 most recent announcements |
flags | object | Factual flags derived from the complete timeline - see below |
coverage | object | window { from, to } - the ingested history window; identity when the Sirene echo is unavailable |
Fields of an event
| Field | Type | Description |
|---|---|---|
family | string | insolvency (collective proceedings: safeguard, receivership, liquidation), deregistration (removals from the register) or sale (business sales and transfers) |
nature | string | Original DILA label (e.g. “Jugement de conversion en liquidation judiciaire”); null when the publication does not state one - never invented |
effective_on | string | Judgment/effect date (YYYY-MM-DD) when distinct from publication; null otherwise |
published_on | string | BODACC publication date (YYYY-MM-DD) |
gazette_issue | string | BODACC gazette issue carrying the announcement |
notice_number | int | Notice number within the gazette issue |
court | string | Court or registry that issued the announcement; null when not stated |
text | string | Short original announcement text (truncated at ingestion) |
The view is capped to the 100 most recent announcements: when a company
has more, truncated is true and total keeps the honest count before the
cap.
Flags: facts, not a score
The flags block states BODACC facts derived mechanically from the
company’s complete timeline - never the filtered view, and never an
opinion:
| Flag | Type | Derivation |
|---|---|---|
has_open_insolvency_announcement | bool | The most recent insolvency announcement is not a closure (mechanical detection of the DILA “clôture” label on its nature) |
is_deregistered | bool | A deregistration has been published in the BODACC |
latest_event | object | { family, date } of the announcement with the most recent effect date across all families; date is the effect date when known, else publication; ties on effect date are broken by the most recent publication; null when the timeline is empty |
has_open_insolvency_announcement: true means exactly this: a collective
proceeding was opened and no closure has been published since. It is a fact
about the gazette, not a solvency opinion or a risk score - the service
does not rate companies. An announcement whose nature is absent is not
treated as a closure: an unknown fact is not a closed proceeding.
Example - insolvency view (SAN MARINA)
GET /company/events?siren=321875205&family=insolvency, against the
2026-07-26 BODACC snapshot - receivership opened in 2022, converted to
judicial liquidation in 2023:
{
"data": {
"siren": "321875205",
"company": {
"name": "SAN MARINA",
"natural_person": null,
"status": "active"
},
"events": [
{
"family": "insolvency",
"nature": "Dépôt de l'état des créances",
"effective_on": "2023-08-25",
"published_on": "2023-09-05",
"gazette_issue": "20230170",
"notice_number": 2594,
"court": "Greffe du Tribunal de Commerce de Marseille",
"text": "L'état des créances est déposé au greffe où tout intéressé peut présenter réclamation devant le juge-commissaire dans le délai d'un mois à compter de la présente publication."
},
{
"family": "insolvency",
"nature": "Jugement de conversion en liquidation judiciaire",
"effective_on": "2023-02-20",
"published_on": "2023-02-23",
"gazette_issue": "20230038",
"notice_number": 1758,
"court": "Greffe du Tribunal de Commerce de Marseille",
"text": "Jugement prononçant la liquidation judiciaire désignant liquidateur SCP J.P Louis & A.Lageat, Mandat Conduit Par Me J.P Louis 30 Rue Cours Lieutaud 13001 Marseille et SAS LES MANDATAIRES mission conduite par Me Vincent DE CARRIERE 50 Rue Sylvabelle 13006 MARSEILLE."
},
{
"family": "insolvency",
"nature": "Jugement d'ouverture d'une procédure de redressement judiciaire",
"effective_on": "2022-09-22",
"published_on": "2022-09-27",
"gazette_issue": "20220187",
"notice_number": 3494,
"court": "Greffe du Tribunal de Commerce de Marseille",
"text": "Jugement prononçant l'ouverture d'une procédure de redressement judiciaire, date de cessation des paiements le 25 août 2022 désignant administrateur SCP Avazeri-Bonetto, Mission Conduite Par Me F.Avazeri 23/29 Rue Haxo 13001 Marseille et SELARL GILLIBERT & ASSOCIES, mission conduite par Me Vincent GILLIBERT 11 Rue Venture 13001 MARSEILLE avec les pouvoirs : assister le débiteur pour tous les actes de gestion, mandataire judiciaire SCP J.P Louis & A.Lageat, Mandat Conduit Par Me J.P Louis 30 Rue…"
}
],
"total": 3,
"truncated": false,
"flags": {
"has_open_insolvency_announcement": true,
"is_deregistered": false,
"latest_event": { "family": "sale", "date": "2024-02-01" }
},
"coverage": {
"window": { "from": "2008-01-01", "to": "2026-07-26" }
}
},
"provenance": {
"source": "dila-bodacc",
"fetched_at": "2026-07-26T18:43:01Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-26T00:00:00Z" }
}
}
Note how the flags illustrate the derivation rule: they read the complete
timeline, not the requested view. total: 3 counts the requested view, but
this SIREN has 36 announcements in all - and latest_event points at one
of the 33 you cannot see here: a business sale (“Achat d’un établissement
secondaire ou complémentaire par une personne morale”, Aix-en-Provence
registry), gazetted on 2024-02-01. That announcement carries no published
effect date, so date falls back to its publication, exactly as the rule
states. Meanwhile the most recently published announcement of the timeline
(2024-05-19) carries an effect date of 2017-05-22 - a sale gazetted seven
years after it took effect - and is not retained: the BODACC routinely
publishes an announcement, sales especially, long after the fact, which is
precisely the trap this field avoids.
has_open_insolvency_announcement is true because the most recent
insolvency announcement (“Dépôt de l’état des créances”) is not a closure.
These values are what the 2026-07-26 snapshot returns. An example served
from a snapshot ages with the store: a newly gazetted announcement can move
latest_event at any refresh, so read the numbers as an illustration for the
as_of shown - only the derivation rule is a contract.
An empty list is a paid answer
The BODACC does not “know” SIRENs - it knows announcements. A well-formed,
checksum-valid SIREN with no announcement is therefore a 200, billed, with
events: [] - never a 404. The absence of announcements is the answer
the agent asked for, and it is only meaningful over a stated window:
coverage.window { from, to } carries the history actually ingested (since
2008) and is served on every response, empty or not.
A real empty answer, captured against the production store on 2026-07-12 (an active sole trader with no BODACC announcement):
{
"data": {
"siren": "902120096",
"company": {
"name": null,
"natural_person": { "last_name": "DEMAILLY", "first_name": "LOLITA" },
"status": "active"
},
"events": [],
"total": 0,
"truncated": false,
"flags": {
"has_open_insolvency_announcement": false,
"is_deregistered": false,
"latest_event": null
},
"coverage": {
"window": { "from": "2008-01-01", "to": "2026-07-12" }
}
},
"provenance": {
"source": "dila-bodacc",
"fetched_at": "2026-07-12T15:07:29Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-12T00:00:00Z" }
}
}
The question “does this company have legal announcements?” received its
answer: none known over the 2008-01-01 -> 2026-07-12 window. The flags
are false and latest_event is null by derivation from the empty
timeline, not by default; the Sirene echo (a natural person: name: null,
natural_person filled) confirms the SIREN exists in the register.
Sirene identity echo
Each answer carries a minimal company echo from the INSEE Sirene
register - legal name (or the natural person’s name for a sole trader) and
active/ceased status - so the agent can cross-read the timeline against the
company’s identity without a second call. For the full identity card
(legal form, NAF activity, workforce, head office), use
GET /company/resolve.
When the SIREN is unknown to the Sirene stock, company is null and
coverage.identity says why ("siren_unknown_to_sirene") - it is never an
error: the BODACC timeline is still served on its own authority.
Freshness
Answers are served from a snapshot of the BODACC dataset, refreshed by
delta; freshness.as_of carries the extraction date of the image that backed
the answer, and coverage.window.to matches it. If a refresh is missed, the
service keeps serving the last good snapshot - honestly dated by as_of -
and never turns staleness into a 5xx.
Errors
Only requests the service cannot answer leave the 200 range - none of them are billed. Note the deliberate absence of a 404 for a well-formed SIREN: no announcements is a 200 (see above).
| Status | code | Case |
|---|---|---|
| 400 | INVALID_INPUT | Malformed SIREN (wrong length, non-digits), or unknown family value (accepted variants listed in the message) |
| 400 | INVALID_CHECKSUM | Well-formed SIREN that fails its Luhn check - a probable typo the agent should fix |
| 400 | MISSING_PARAMETER | No siren provided |
| 404 | NOT_FOUND | Unknown routes only - never a well-formed SIREN |
| 503 | DATA_UNAVAILABLE | The BODACC store has not been ingested yet - there is no last good snapshot to serve |
| 500 | INTERNAL | Internal error (detail logged, not exposed) |
{ "error": "invalid checksum for siren `321875206`", "code": "INVALID_CHECKSUM" }
Attribution
Legal-announcement data is derived from the BODACC (Bulletin officiel des annonces civiles et commerciales), published by DILA under the Licence Ouverte / Open Licence (Etalab). The identity echo comes from the Sirene register published by INSEE, under the same licence.
See also
GET /company/resolve- the full official identity card behind the SIREN: legal name, status, legal form, NAF activity, head office.GET /iban/screen- screen a counterparty’s IBAN against the OFAC/EU/UN sanctions lists before paying it.- For agents - discovery surfaces, the live
/catalogand how settlement works.