Clients
L'objet customer représente une entité destinataire de vos factures — particulier (B2C) ou personne morale (B2B).
Les clients B2B sont validés et pré-remplis à partir des données officielles INSEE (SIRET, raison sociale, code NAF, adresse du siège) et du service VIES (UE) pour les numéros de TVA intra-communautaires.
Endpoints
| Méthode | Chemin | Description |
|---|---|---|
| POST | /v1/customers | Créer un client |
| GET | /v1/customers | Lister les clients |
| GET | /v1/customers/:id | Récupérer un client |
| PATCH | /v1/customers/:id | Modifier un client |
| DELETE | /v1/customers/:id | Supprimer (soft-delete) |
| POST | /v1/customers/lookup | Recherche par SIRET (pré-remplissage INSEE) |
| POST | /v1/customers/import | Import CSV en lot |
| GET | /v1/customers/export | Export CSV |
Créer un client
$ curl -X POST https://facturino.com/api/v1/customers \
-H "Authorization: Bearer fac_test_..." \
-H "Idempotency-Key: customer-create-acme-2026" \
-H "Content-Type: application/json" \
-d '{
"name": "Durand & Associés SARL",
"siret": "00012345500008",
"vatNumber": "FR31000123455",
"address": {
"line1": "15 rue de la Paix",
"city": "Paris",
"postalCode": "75002",
"country": "FR"
},
"contacts": [
{ "firstName": "Marie", "lastName": "Dupont", "email": "compta@durand.fr" }
],
"paymentTerms": 30,
"defaultPaymentMethod": "transfer"
}' Réponse :
{
"id": "cus_8f2k4m9n",
"object": "customer",
"livemode": false,
"name": "Durand & Associés SARL",
"siret": "00012345500008",
"vatNumber": "FR31000123455",
"siretVerified": false,
"vatVerified": false,
"address": {
"line1": "15 rue de la Paix",
"city": "Paris",
"postalCode": "75002",
"country": "FR"
},
"contacts": [
{
"firstName": "Marie",
"lastName": "Dupont",
"email": "compta@durand.fr"
}
],
"paymentTerms": 30,
"defaultPaymentMethod": "transfer",
"created": "2026-04-22T13:48:10.000Z",
"updated": "2026-04-22T13:48:11.000Z"
} Champs principaux
| Champ | Type | Requis | Notes |
|---|---|---|---|
name | string | oui | Raison sociale ou nom complet (max 200 caractères) |
siret | string | B2B FR | 14 chiffres, validation Luhn appliquée |
vatNumber | string | B2B UE | Format FR31000123455, validé via VIES en async |
address | object | oui | line1, line2?, city, postalCode, country (ISO 3166) |
contacts | array | non | Liste de contacts (firstName, lastName, email, phone) — max 10. |
paymentTerms | integer | non | Délai de paiement par défaut en jours (0–365). Hérité par les factures émises au client. |
defaultPaymentMethod | enum | non | transfer, card, check, cash, direct_debit, sepa, paypal. |
tags | string[] | non | Étiquettes libres (max 20 tags, 50 caractères chacun) pour filtrage / segmentation. |
type | enum | non | company (défaut) ou individual. |
metadata | object | non | Clés-valeurs libres pour vos propres références. |
Validation TVA et SIRET
À la création ou mise à jour, Facturino lance en arrière-plan :
- SIRET : validation Luhn synchrone + enrichissement à partir des données officielles INSEE (raison sociale officielle, code NAF, adresse du siège). Le booléen
siretVerifiedpasse àtruelorsque le SIRET est trouvé dans le répertoire SIRENE, sinon restefalse. - Numéro TVA : validation VIES asynchrone (15 s timeout). Le champ booléen
vatVerifiedpasse àtrueaprès confirmation, ou restefalseen cas d'échec / d'indisponibilité du service.
Tant que la validation n'est pas confirmée, vatVerified reste false. Ce
booléen historique ne distingue pas un numéro invalide d'un service VIES indisponible : ne
l'utilisez jamais seul pour accorder un traitement à 0 %. Ces validations ne bloquent pas la
création du client.
Preuve fiscale. Le parcours Décisions fiscales
conserve un résultat VIES daté avec quatre états distincts : valid,
invalid, unavailable et invalid_format. Une indisponibilité
produit une décision pending_verification : aucun paiement ni taux à 0 % n'est
accordé par défaut.
Recherche et enrichissement
POST /v1/customers/lookup renvoie les informations officielles INSEE associées à un SIRET sans créer de client — utile pour pré-remplir un formulaire en temps réel.
$ curl -X POST "https://facturino.com/api/v1/customers/lookup" \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-d '{"siret": "00012345500008"}'
# Réponse — informations officielles INSEE pré-remplies depuis le SIRET
{
"object": "sirene_lookup",
"found": true,
"data": {
"name": "DURAND & ASSOCIES",
"siret": "00012345500008",
"siren": "000123455",
"vatNumber": "FR31000123455",
"legalForm": { "code": "5499", "sigle": "SARL", "label": "Société à responsabilité limitée" },
"naf": { "code": "62.02A", "label": "Conseil en systèmes et logiciels informatiques" },
"address": { /* ... */ },
"active": true
}
}
Vous pouvez aussi rechercher par query (recherche floue sur le nom) ou par vatNumber. Le résultat inclut une suggestion d'address
et de legalForm à valider par l'utilisateur avant création.
Import CSV
Pour migrer un catalogue existant, utilisez l'import CSV :
$ curl -X POST https://facturino.com/api/v1/customers/import \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-d '{"csv": "name,email\nAcme SAS,contact@acme.fr"}'
# Réponse 200 OK — traitement synchrone, compte des lignes importées
{
"object": "import_result",
"imported": 2,
"errors": [],
"total_rows": 2
} Format attendu (UTF-8, séparateur virgule, header obligatoire). Seule la colonne name est requise :
name,siret,vat_number,address_line1,address_city,address_postal_code,address_country,email,phone
"Durand & Associés","00012345500008","FR31000123455","15 rue de la Paix","Paris","75002","FR","compta@durand.fr","+33145678910"
"Acme Corp","00012345600006","FR34000123456","2 avenue des Champs","Lyon","69003","FR","invoice@acme.com",
Limites : 10 000 lignes par fichier, 2 imports par heure. Les erreurs ligne-par-ligne sont retournées directement dans la
réponse (tableau errors avec le numéro de ligne et le détail des champs invalides). Si aucune ligne n'est
importée alors que des erreurs sont présentes, la réponse est un 422.
Contacts
Chaque client peut avoir jusqu'à 10 contacts, chacun avec un role facultatif parmi
billing, technical et main :
role = "billing"— reçoit les factures et les relances par défaut. À défaut de contactbilling, l'envoi retombe sur l'email principal du client (email).role = "technical"— contact technique (intégration, rejets PA, anomalies).role = "main"— contact général de l'entité.
Mettre à jour les contacts via PATCH :
curl -X PATCH https://facturino.com/api/v1/customers/cus_8f2k4m9n \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{ "firstName": "Marie", "lastName": "Dupont", "email": "marie@durand.fr", "role": "billing" },
{ "firstName": "Paul", "lastName": "Martin", "email": "paul@durand.fr", "role": "technical" }
]
}' Clients B2C
Pour des particuliers, le champ siret est facultatif. Précisez type: "individual" :
{
"type": "individual",
"name": "Jean Dupont",
"address": { "line1": "1 rue Example", "city": "Paris", "postalCode": "75001", "country": "FR" },
"contacts": [{ "email": "jean@example.com" }]
} Les factures B2C sont émises sans dépôt PA (la facturation électronique obligatoire 2026 ne couvre que le B2B intracommunautaire). Elles restent générées en Factur-X mais ne déclenchent pas de transmission DGFiP.
Soft-delete
DELETE /v1/customers/:id marque le client comme supprimé (deleted: true) sans purger les données
— les factures historiques restent inchangées. Les clients supprimés sont exclus par défaut des listes ; ajoutez
?include_deleted=true pour les inclure.
Pour une suppression définitive (RGPD, droit à l'oubli), utilisez POST /v1/account/export (portabilité art. 20)
puis demandez la suppression manuelle au support — l'opération est irréversible et peut nécessiter de purger des factures liées.
Étapes suivantes
- Factures — utiliser le client comme destinataire
- Produits — catalogue réutilisable dans les lignes
- Webhooks — événements
customer.*
Avertissement sur la nature de l’acheteur
La réponse peut ajouter warnings, tableau en lecture seule de BuyerNatureWarning. Chaque objet porte code: buyer_nature_suspect, un message anglais et param, le champ à vérifier. Le client ou la décision est créé malgré cet avertissement.
Un nom qui semble désigner une entreprise sur un client particulier ou sans SIRET déclenche ce signal : par exemple « SAS ALPHA MENUISERIE ». Vérifiez le type du client et son SIRET avant de décider le canal de facturation. « Marie Sasu » ne déclenche pas cet avertissement.
Entreprise à diffusion restreinte
La recherche POST /v1/customers/lookup retourne data.disclosure (ou results[].disclosure pour une recherche par nom) : status vaut O, P, N ou null si le registre ne le précise pas ; withheldFields liste les champs masqués, par exemple name et address.line1.
Les marqueurs [NON-DIFFUSIBLE] et [ND] deviennent des chaînes vides dans Sirene, ou null dans VIES, qui filtre aussi ---. Si une partie de la voie est masquée, toute la ligne de voie revient vide. Les champs publics, comme la commune, restent disponibles. Demandez la raison sociale et l’adresse au client, sur ses propres documents ; aucune donnée de remplacement n’est inventée.
La diffusion est lue aux deux niveaux : statut_diffusion pour l’unité légale et statut_diffusion_etablissement pour l’établissement demandé. Le statut le plus restrictif est retenu (N, puis P, puis O). Une société en diffusion partielle peut garder une dénomination publique : seuls les champs portant effectivement un marqueur sont vidés et listés. Une recherche par SIRET utilise l’établissement correspondant dans matching_etablissements, sinon le siège seulement si son SIRET correspond ; une adresse d’un autre établissement n’est jamais attribuée au SIRET demandé.
La création, la modification et l’import CSV d’un client refusent ces marqueurs. La finalisation d’une facture ou d’un avoir les refuse aussi, avant numérotation, avec buyer_identity_not_disclosed (400) et le champ à corriger dans param. Corriger une fiche client ne réécrit jamais l’instantané d’un document finalisé. siretVerified atteste seulement que le registre a renvoyé un résultat, pas que le nom et l’adresse saisis sont certifiés.
Pour annuler une facture déjà émise contenant un marqueur, un avoir total peut reprendre le nom et l’adresse corrigés de la même fiche client. La facture d’origine demeure conservée avec ses données figées ; aucun avoir ne peut être finalisé avec une identité encore masquée.