GET /company/report

Complete due diligence on a French company in one paid response, by SIREN: official identity (Sirene) + dated legal events (BODACC) + live VAT validation (VIES) + Peppol e-invoicing reachability + the global GLEIF identity and its ultimate consolidating parent - five blocks, each carrying its own provenance. This is the showcase of the “Company” family and of the whole pre-action checks suite: the unit endpoints consolidated into a single settlement.

The counterparty pre-action check. Before you invoice, pay or onboard: an agent about to act with a company gets, in one paid call, the facts that matter - is it real and still active, is there an open insolvency proceeding, is its VAT number valid right now, can it receive an e-invoice on Peppol, and which group consolidates it. No account, no API key, no Creditsafe/Pappers subscription. See the live /catalog for the authoritative endpoint listing and price.

The value is in the crossing. Take SAN MARINA (real store example below): its Sirene status alone reads active, but the report shows the judicial liquidation opened at the BODACC right beside it. Two sourced facts served side by side - never fused into a verdict. That juxtaposition is the pitch.

Parameters

The report is by SIREN: siren only - no siret=, no vat=, no search by name on this route.

ParameterTypeRequiredDescription
sirenstringyes9-digit French SIREN (Luhn-checked)
includestringnoCSV subset of identity,events,vat,peppol,lei (default: all). identity is always served (the base), even if not listed
GET /company/report?siren=333285633
GET /company/report?siren=321875205&include=identity,events,peppol
  • include= selects which blocks to build. Omit it and you get all five.
  • Without vat, the report is 100% offline - zero network at call time (VIES is the service’s only outbound call). include=identity,events,peppol,lei answers in milliseconds.
  • An unknown value in include= is a 400 INVALID_INPUT (not billed).

The base identity is what makes the report exist

The identity block is the base, and its presence is the condition of the report. A well-formed SIREN that is unknown to the Sirene register is a 404 NOT_FOUND, not billed - the gateway does not settle, and no empty report is ever served or charged.

This is the deliberate difference with the unit endpoints /company/events and /company/peppol taken in isolation, where an absence (no gazette entry, not on Peppol) is itself a paid 200 answer. A report with no identity has no object - so here the absence of identity is a 404, while the absence of a secondary fact is a served, honest block.

x402 golden rule and the status matrix

The agent pays for due diligence that ran, in a single settlement - including a degraded or partial report. Only requests the service cannot answer leave the 200 range, and none of those are billed.

CaseResult
Known SIREN200, billed - report served, even degraded (a block unavailable/unverifiable) or partial (include=)
Well-formed SIREN unknown to the register404 NOT_FOUND, not billed - no empty report
siren missing / not 9 digits / Luhn fails / bad include=400, not billed (see Errors)

Provenance per block - the central contract

The heart of this endpoint: each block carries its own provenance, and they are never smoothed under one date. The five sources are dated differently - Sirene is a month-end snapshot, BODACC an extraction date, Peppol an export date, VIES a live check - and the response says so, block by block. The root provenance reflects the identity base (insee-sirene).

200 response - UnifiedResponse

{
  "data": {
    "siren": "…",
    "identity": { "…": "exact shape of /company/resolve, own provenance" },
    "events":   { "…": "exact shape of /company/events, own provenance" },
    "vat":      { "…": "exact shape of /company/vat, own provenance" },
    "peppol":   { "…": "exact shape of /company/peppol, own provenance" },
    "lei":       { "…": "global GLEIF identity + ultimate parent, own provenance" },
    "summary":  { "…": "mechanically-derived facts, not a score" },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "insee-sirene",
    "fetched_at": "2026-07-12T21:17:29Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-30T00:00:00Z" }
  }
}

Each block has exactly the shape of its unit endpoint - so the field-level documentation of a block is the documentation of the corresponding endpoint:

BlockShape / detail docOwn provenance source
identityGET /company/resolveinsee-sirene (snapshot)
eventsGET /company/eventsdila-bodacc (snapshot)
vatGET /company/vatvies + pure-computation (live)
peppolGET /company/peppolpeppol-directory (snapshot)
leiGET /company/lei + /company/ownershipgleif (snapshot)

Secondary blocks are best-effort - never a 5xx

Once identity succeeds, the secondary blocks are best-effort. A missing dataset or a VIES outage degrades a block, it never fails the report:

  • Dataset not ingested (BODACC, Peppol or GLEIF) → the block becomes { "unavailable": "bodacc_dataset_unavailable" } (resp. "peppol_dataset_unavailable", "gleif_dataset_unavailable"), the report is served anyway, and the absence is stated by coverage.unavailable - never silent.
  • VIES outage → the vat block is status: "unverifiable" with a reason, its provenance reduced to pure-computation (only the local syntax check is claimed). A 200, never a 5xx (real example below).
  • Sirene never ingested (the base is impossible) → 503 DATA_UNAVAILABLE. This is distinct from a missed refresh, where the last good snapshot is served with its honest as_of - staleness is never turned into a 5xx.

Everything is said by coverage: complete, unavailable (degraded blocks), excluded (blocks dropped by include=) - never a silent absence.

summary - mechanically-derived facts, not a score

summary is a synthesis derived mechanically from the served blocks:

FieldSourceMeaning
statusSireneactive / ceased
has_open_insolvency_announcementBODACCopen insolvency proceeding, yes/no
vat_statusVIESvalid / invalid / unverifiable
peppol_reachablePeppolreachable on the directory, yes/no
leiGLEIFthe attached LEI, only when it is unique

It is not a score. Never a rating, a recommendation, or a “risk score” - this is the house rule on provenance and truthfulness (scoping decision 2026-07-11). A field absent from summary means the block was excluded by include= or unavailable - said by coverage, never silent.

Example - full report, VIES live

GET /company/report?siren=333285633 (EQUIPTEC - all five blocks served, coverage.complete: true, ~0.3 s dominated by the live VIES check; production store, Sirene 2026-06-30 / GLEIF 2026-07-28):

{
  "data": {
    "siren": "333285633",
    "identity": {
      "siren": "333285633",
      "name": "EQUIP'TEC",
      "status": "active",
      "legal_form": { "code": "5710", "label": "SAS, société par actions simplifiée" },
      "main_activity": { "code": "46.69B", "label": "Commerce de gros …", "nomenclature": "NAFRev2" },
      "created_on": "1985-08-01",
      "headquarters": {
        "siret": "33328563300033",
        "status": "active",
        "address": { "line": "1 RUE DE L’INDUSTRIE", "postal_code": "62220", "city": "CARVIN", "country": null }
      },
      "coverage": { "missing": [] },
      "provenance": {
        "source": "insee-sirene",
        "fetched_at": "2026-07-12T21:17:29.335151695Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-06-30T00:00:00Z" }
      }
    },
    "events": {
      "siren": "333285633",
      "company": { "name": "EQUIP'TEC", "natural_person": null, "status": "active" },
      "events": [
        {
          "family": "sale",
          "nature": "Achat d'un fonds par une personne morale (insertion provisoire)",
          "published_on": "2009-05-06",
          "gazette_issue": "20090087",
          "court": "GREFFE DU TRIBUNAL DE COMMERCE DE ROUBAIX-TOURCOING"
        }
      ],
      "total": 1,
      "truncated": false,
      "flags": {
        "has_open_insolvency_announcement": false,
        "is_deregistered": false,
        "latest_event": { "family": "sale", "date": "2009-05-06" }
      },
      "coverage": { "window": { "from": "2008-01-01", "to": "2026-07-12" } },
      "provenance": {
        "source": "dila-bodacc",
        "fetched_at": "2026-07-12T21:17:29.335151695Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-07-12T00:00:00Z" }
      }
    },
    "vat": {
      "vat_number": "FR20333285633",
      "country": "FR",
      "syntax_valid": true,
      "status": "valid",
      "name": "SAS EQUIP'TEC",
      "derived_from_siren": "333285633",
      "checked_at": "2026-07-12T21:17:29.632129817Z",
      "provenance": {
        "source": "vies + pure-computation",
        "fetched_at": "2026-07-12T21:17:29.632129817Z",
        "freshness": { "kind": "live" }
      }
    },
    "peppol": {
      "reachable": true,
      "participants": [
        { "id": "0009:33328563300033", "scheme": "0009", "value": "33328563300033", "country": "FR", "names": ["EQUIPTEC"], "registered_on": "2023-03-27", "document_types": ["… declared document types, see /company/peppol"] }
      ],
      "company": { "name": "EQUIP'TEC", "natural_person": null, "status": "active" },
      "coverage": {
        "directory_as_of": "2026-07-12",
        "note": "reachability reflects the public Peppol directory export dated directory_as_of, not a live SMP lookup"
      },
      "provenance": {
        "source": "peppol-directory",
        "fetched_at": "2026-07-12T21:17:29.335151695Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-07-12T00:00:00Z" }
      }
    },
    "lei": {
      "lei": "969500EQMDAO9YAZN902",
      "legal_name": "EQUIP'TEC",
      "entity_status": "ACTIVE",
      "registration_status": "ISSUED",
      "verified_against_sirene": true,
      "total_matches": 1,
      "ultimate_parent": {
        "status": "reporting_exception",
        "link": null,
        "exception": { "category": "ULTIMATE_ACCOUNTING_CONSOLIDATION_PARENT",
                       "reasons": ["NATURAL_PERSONS"] }
      },
      "limits": "Relationships are self-declared … NOT beneficial ownership under AML/KYC rules …",
      "provenance": {
        "source": "gleif",
        "fetched_at": "2026-07-29T15:50:39Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
      }
    },
    "summary": {
      "status": "active",
      "has_open_insolvency_announcement": false,
      "vat_status": "valid",
      "peppol_reachable": true,
      "lei": "969500EQMDAO9YAZN902"
    },
    "coverage": { "complete": true }
  },
  "provenance": {
    "source": "insee-sirene",
    "fetched_at": "2026-07-12T21:17:29.335151695Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-30T00:00:00Z" }
  }
}

Note the provenance per block: five sources, four different snapshot dates plus one live check - never smoothed under a single date. EQUIPTEC holds a LEI, and Level 2 says why it declares no consolidating parent (NATURAL_PERSONS: it is held by individuals, who have no LEI). The root provenance is that of the identity base.

Example - include= partial, 100% offline (the crossing value)

GET /company/report?siren=321875205&include=identity,events,peppol (SAN MARINA - the vat block is dropped, so zero network, answered in ~4 ms; the real BODACC timeline of 36 notices is abridged here to the two most significant, the real response carries them all; production store, 2026-07-26):

{
  "data": {
    "siren": "321875205",
    "identity": {
      "siren": "321875205",
      "name": "SAN MARINA",
      "status": "active",
      "…": "exact shape of /company/resolve, provenance insee-sirene snapshot 2026-06-30"
    },
    "events": {
      "siren": "321875205",
      "company": { "name": "SAN MARINA", "natural_person": null, "status": "active" },
      "events": [
        {
          "family": "insolvency",
          "nature": "Jugement de conversion en liquidation judiciaire",
          "effective_on": "2023-02-20",
          "published_on": "2023-02-23",
          "court": "Greffe du Tribunal de Commerce de Marseille"
        },
        {
          "family": "insolvency",
          "nature": "Dépôt de l'état des créances",
          "effective_on": "2023-08-25",
          "published_on": "2023-09-05",
          "court": "Greffe du Tribunal de Commerce de Marseille"
        }
      ],
      "total": 36,
      "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:41.814096541Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-07-26T00:00:00Z" }
      }
    },
    "peppol": {
      "reachable": false,
      "participants": [],
      "company": { "name": "SAN MARINA", "natural_person": null, "status": "active" },
      "coverage": {
        "directory_as_of": "2026-07-26",
        "note": "reachability reflects the public Peppol directory export dated directory_as_of, not a live SMP lookup"
      },
      "provenance": {
        "source": "peppol-directory",
        "fetched_at": "2026-07-26T18:43:41.814096541Z",
        "freshness": { "kind": "snapshot", "as_of": "2026-07-26T00:00:00Z" }
      }
    },
    "summary": {
      "status": "active",
      "has_open_insolvency_announcement": true,
      "peppol_reachable": false
    },
    "coverage": { "complete": false, "excluded": ["vat"] }
  },
  "provenance": {
    "source": "insee-sirene",
    "fetched_at": "2026-07-26T18:43:41.814096541Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-06-30T00:00:00Z" }
  }
}

Two things to read here. The value of the crossing: the Sirene status alone says active, the BODACC says the judicial liquidation is open (summary.has_open_insolvency_announcement: true) - two sourced facts served side by side, never fused into a verdict. The include= contract: the vat block is absent, so is summary.vat_status, and coverage = { complete: false, excluded: ["vat"] } says it explicitly - never a silent absence. Note also that flags.latest_event names a sale that is not among the two notices excerpted above: the flags are derived from the complete 36-notice timeline, never from what an excerpt - or a filtered view - happens to show.

The values above are those of the 2026-07-26 snapshot. An example served from a snapshot ages with the store: a newly gazetted announcement can move latest_event, so read the numbers as an illustration for the as_of shown - only the derivation rule is a contract.

The lei block - global identity and who consolidates the counterparty

The lei block carries the GLEIF attachment of the SIREN and ultimate_parent, the consolidating group head. That parent is the point of the block: a spotless French counterparty owned by a sanctioned entity is exactly the case an endpoint-by-endpoint check walks past.

{
  "lei": {
    "lei": "1VUV7VQFKUOQSJ21A208",
    "legal_name": "CREDIT AGRICOLE CORPORATE AND INVESTMENT BANK",
    "entity_status": "ACTIVE",
    "registration_status": "ISSUED",
    "verified_against_sirene": true,
    "total_matches": 1,
    "ultimate_parent": {
      "status": "declared",
      "link": {
        "lei": "969500TJ5KRTCJQWXH05",
        "entity": { "legal_name": "CREDIT AGRICOLE SA", "legal_country": "FR", "…": "…" },
        "relationship_status": "ACTIVE",
        "period": { "start": "2018-01-01", "end": null }
      },
      "exception": null
    },
    "limits": "Relationships are self-declared … NOT beneficial ownership under AML/KYC rules …",
    "provenance": {
      "source": "gleif",
      "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
    }
  }
}

Four things this block does not say:

  • ⚠️ ultimate_parent is the accounting consolidation parent, never the ultimate beneficial owner under AML/KYC rules, and Level 2 publishes no ownership percentage. The response repeats it itself in limits - the same fixed sentence as GET /company/ownership, where the distinction is spelled out in full.
  • ultimate_parent is absent when the attachment is ambiguous or non-existent: walking the control chain of one LEI picked at random among several would name a wrong group head.
  • total_matches: 0 is an answer (“this company has no LEI”), not an unavailability - so the block is served, not marked unavailable. It is the case of the vast majority of French companies (169,049 SIREN bridged at the 2026-07-28 image).
  • The identity fields follow the same rule as the lei block of GET /company/resolve: total_matches is always told, the rest is filled in only when the LEI is unique.

The block is 100% offline: include=identity,events,peppol,lei is a report with zero outbound network - VIES remains the service’s only outbound call.

Example - VIES outage = degraded block, never a 5xx

VIES_BASE_URL pointed at a closed port, full call through the gateway - 200 in ~18 ms, only the vat block degraded (e2e E-402, 2026-07-12):

{
  "vat": {
    "vat_number": "FR20333285633",
    "country": "FR",
    "syntax_valid": true,
    "status": "unverifiable",
    "reason": "network_unreachable",
    "derived_from_siren": "333285633",
    "provenance": { "source": "pure-computation", "freshness": { "kind": "live" } }
  }
}

summary.vat_status: "unverifiable", the three other blocks intact, coverage.complete: true (the block was served, degraded honestly) - the block’s provenance claims only the local computation, never a VIES result it did not get.

Pricing - the whole report at the flat grid price

/company/report sits on Invoket’s uniform flat grid, same price as any unit endpoint - yet it bundles four consolidated offline lookups plus one live check in a single settlement, a composite answer that would otherwise be five separate calls. The exact amount is served by the live /catalog and is never hard-coded here; the report’s value is the consolidation and the cross-check.

Freshness

Each block carries its own freshness. identity is a month-end Sirene snapshot, events a BODACC extraction snapshot, peppol a dated directory export, lei a dated GLEIF Golden Copy image, vat a live VIES check. The root provenance mirrors the identity base. A missed refresh keeps serving the last good snapshot with its honest as_of - staleness is never a 5xx.

Limits

Stated plainly, so the agent knows what the report does and does not claim:

  • By SIREN only - no siret=, no vat=, no search by name on this route.
  • Each block inherits its unit endpoint’s limits: BODACC window 2008+, a dated Peppol photo (not a live SMP lookup), VIES availability varying by member state, GLEIF relationships that are self-declared accounting consolidation, not beneficial ownership.
  • The five sources are dated differently - which is exactly why provenance is per block, never smoothed.
  • summary states sourced facts, not an opinion - no rating, no score, no recommendation.

Errors

Only requests the service cannot answer leave the 200 range - none are billed. Note the difference from the unit endpoints: an unknown SIREN here is a 404 (no empty report), whereas on /company/events or /company/peppol an absence is a paid 200.

StatuscodeCase
400MISSING_PARAMETERsiren absent
400INVALID_INPUTsiren not 9 digits / non-digits; unknown value in include=
400INVALID_CHECKSUMsiren fails its Luhn check - a probable typo the agent should fix
404NOT_FOUNDWell-formed SIREN unknown to the Sirene register (no empty report); unknown routes
503DATA_UNAVAILABLEThe Sirene dataset has never been ingested - the base cannot be built
500INTERNALInternal error (detail logged, not exposed)
{ "error": "unknown value in 'include=': expected a subset of identity,events,vat,peppol,lei", "code": "INVALID_INPUT" }

Sources and licences

Each block carries its own source, dated in its own provenance:

  • identity - INSEE Sirene register (Licence Ouverte / Etalab, month-end image).
  • events - BODACC / DILA (Licence Ouverte / Etalab, extraction date).
  • vat - VIES, the European Commission’s public VAT validation service (live, no key).
  • peppol - the public Peppol directory export, data published by the network’s participants, attribution OpenPeppol (export date).
  • lei - the GLEIF Level 1 and Level 2 Golden Copy (CC0 1.0, publication date of the ingested image).

See also

The report is the “counterparty onboarding” suite. Need just one fact? Each block is its own unit endpoint, at the same flat grid price - see the /catalog:

Then, verify the company, screen the account, check the contact before you act:

And the counterparty vs. the document - the full French 2026-2027 invoicing cycle: