SIREN Capture
The SIREN is the nine-digit number that identifies a company in the French business register. France requires a B2B invoice to carry the buying company's identifier, so vivenu cannot issue a compliant invoice for a French business buyer without it.
Sellers registered in France therefore enable the SIREN Capture module. Once it is on, a checkout that carries a company name has to carry a SIREN as well before it can be completed, and the number travels from the checkout onto the transaction and the invoice — including invoices handed to an external system through Invoice Synchronization.
The vivenu checkout collects the number on its own. If you built your own checkout on top of the Checkout API, you have to collect and submit it yourself, otherwise your checkouts start failing on the day the module is switched on.
Nothing changes for sellers without the module, for sellers outside France, or for checkouts without a company name.
Before you test
The module has to be enabled for the seller before any of this becomes observable. With it off the checkout behaves exactly as it did before, and there is no way to try the new behaviour.
Have it enabled on a test seller first and adapt your integration against it. Only once your checkouts complete there — business buyer, French address, SIREN submitted — should it be enabled in production. Turning it on in production before the integration handles it will make every B2B checkout for a French buyer fail.
How it works
- You read the requirements from the details form. It tells you which identification documents the seller can ask for, and under which conditions each of them applies.
- You evaluate those conditions against the checkout in front of you. Only the buyer's company and country decide whether a SIREN is needed, so the answer changes while the customer is filling in the form.
- You submit the number together with the address when you post the checkout details. vivenu validates it and rejects the request if a required document is missing.
When a SIREN is required
A SIREN is required once both of these hold:
- a company name is set on the checkout, and
- the buyer country is one of
FR,GP,MQorRE— the French VAT territories — or is not known yet.
An unknown country does not exempt a checkout. It keeps the requirement active and forces the address to be collected, so that the rule can be re-evaluated against the real country once you know it. Always send country.
Whenever a SIREN is required, a full address — street, postal, city and country — is required with it. Please note that this takes precedence over the event setting "Don't capture address data" (skipAddressInfo): even if every event in the checkout has it enabled, the address becomes mandatory as soon as the SIREN requirement applies.
Reading the requirements
GET /api/checkout/{id}/detailsform describes what the checkout has to collect. It returns the seller's full identification configuration, not only the requirements that currently apply — evaluating the conditions is left to you.
type Requirement = {
type: 'france_siren'
requireAddress?: boolean // the full address is mandatory while this applies
forceForB2B?: boolean // applies as soon as a company name is set
forceForInternational?: boolean // applies when the buyer country differs from the seller country
applicableBuyerCountries?: string[] // restricted to these buyer countries, absent means all
identificationThreshold?: number // applies from this order total upwards
}
type DetailsForm = {
skipAddressInfo: boolean
enforceAddress?: boolean
identificationConfig?: Requirement[][]
}
For a French seller with the module enabled, the configuration looks like this:
{
"skipAddressInfo": false,
"enforceAddress": true,
"identificationConfig": [
[
{
"type": "france_siren",
"requireAddress": true,
"forceForB2B": true,
"applicableBuyerCountries": ["FR", "GP", "MQ", "RE"]
}
]
]
}
identificationConfig is a list of groups. Every group has to be satisfied, and a group is satisfied by any one of the documents it lists. A requirement inside a group applies when it is applicable for the buyer country, and at least one of identificationThreshold, forceForB2B or forceForInternational matches. A requirement without a threshold is never triggered by the order total alone.
skipAddressInfo and enforceAddress are evaluated against the current state
of the checkout, so they change the moment a company name is added. Read the
details form again after updating the company instead of caching the first
response.
Submitting the number
Send the SIREN as an identification document on POST /api/checkout/{id}/details, together with the address. The same identification field exists on POST /api/purchaseintents.
{
"company": "ACME SAS",
"street": "1 Rue de Rivoli",
"postal": "75001",
"city": "Paris",
"country": "FR",
"identification": [{ "type": "france_siren", "identifier": "732829320" }]
}
The identifier has to be exactly nine digits and pass the SIREN checksum. Only leading and trailing whitespace is trimmed, so strip the spaces and separators French companies commonly print their number with before you send it.
A france_siren document sent while the module is off, or for a seller outside France, is silently dropped rather than rejected.
Errors
A checkout that does not meet the requirements is rejected with a 400:
Missing required identification: france_siren— a company name is set for a French buyer, but no SIREN was sent.Address is required— the SIREN applies, but the address is missing or incomplete.- A validation error on
identification— the number is not nine digits, or it fails the checksum.
Test values
There is no sandbox range. The number is only checked against its checksum and is not looked up in the business register, so any number passing the checksum is accepted.
| SIREN | Result |
|---|---|
552100554 | Valid — Peugeot SA |
443061841 | Valid — Google France |
356000000 | Valid — La Poste |
552100555 | Invalid — checksum |
123456789 | Invalid — checksum |
55210055, 5521005544 | Invalid — wrong length |
55210055A, ABC123456 | Invalid — not all digits |
552 100 554 | Invalid — inner spaces are not stripped |