# Basile API > Base de données B2B française. Sociétés : 26 758 354 au registre légal, dont 12 878 867 au statut > ACTIF — c'est ce dernier chiffre qui compte pour un ciblage ; s'y ajoutent 5 458 086 fiches Google > My Business et 5 276 024 pages LinkedIn d'entreprises. Contacts : 20 825 880 dirigeants au registre > et 28 916 355 profils LinkedIn de personnes. Une recherche interroge les sources concernées puis > réunit les résultats, donc un total peut dépasser le volume d'une source prise seule. > API REST sur https://api.basile.cc. > Auth : header `Authorization` avec la clé API brute (PAS de préfixe `Bearer`), `Content-Type: application/json`. ## Ressources machine-readable - [Spécification OpenAPI (YAML)](/openapi.yaml) : tous les endpoints, filtres, schémas de requête/réponse. - [Skill Claude (ZIP)](/basile-skill.zip) : skill prête à l'emploi (recherche, comptage, export, enrichissement). - [Référence skill (JSON)](/skill-reference.json) : métadonnées de la skill. ## Endpoints clés - `POST /people/find` — chercher/compter des personnes (body `{ filters, limit, countOnly, paginationToken }`). `total` = nombre de résultats. **Compter est gratuit ; récupérer les enregistrements est décompté de votre forfait** (voir Facturation). - `POST /companies/find` — chercher des entreprises. Renvoie `total` (sociétés dédupliquées) et `establishmentsTotal` (points de vente / fiches Google). - `POST /people/export` · `POST /companies/export` — export CSV (companies : param `mode` = `"companies"` | `"locations"`). Consomme du quota. - `GET /companies/activity-suggest?q=` — IDs de concept unifiés pour le filtre `activity` (métier/secteur, people ET companies). - `POST /enrichment/find` puis `GET /enrichment/find/{id}` : e-mail et numéro de n'importe quelle personne, payés sur le solde d'enrichissement (voir Enrichissement). ## find vs export : ce que chacun renvoie (IMPORTANT) Les deux acceptent exactement les mêmes `filters`. La différence est la **richesse des données**. - **PERSONNES — `/people/find` renvoie la personne, PAS sa société.** Vous obtenez son identité, sa localisation, son poste, son URL LinkedIn, plus le **nom** et l'**identifiant interne** de son employeur. Vous n'obtenez **pas** les données de cette société : ni SIREN/NAF/forme juridique (Legal), ni effectif/secteur/description (LinkedIn), ni note/avis/adresse (Google Maps). - **PERSONNES : `/people/export` renvoie la ligne complète : 92 colonnes.** 22 sur la personne, **18 sur sa société LinkedIn**, **31 sur sa société au registre légal**, **11 Google Maps**, 6 drapeaux de présence. Pour UNE fiche, `GET /people/{id}/full` rend le même modèle sans passer par un export. - **ENTREPRISES — `/companies/find` croise DÉJÀ les trois sources.** Chaque résultat porte sa fiche plus, quand la correspondance existe, les données des deux autres sources sous `x_legal` / `x_lki` / `x_gmb`. Contrairement aux personnes, il n'est pas nécessaire d'exporter pour voir les trois sources. - **ENTREPRISES : `/companies/export` renvoie 70 colonnes** : les mêmes données mises à plat en CSV (31 Legal, 11 Google Maps, le reste LinkedIn + identité + drapeaux). - **Comptes annuels** : `GET /companies/{id}/full` et `GET /people/{id}/full` (employeur de la personne, par `row.legal_siren`) portent `finances` : `{ siren, exercices: [{ annee, date_cloture, chiffres, evolutions, rupture_perimetre, capture_le }] }`, du plus récent au plus ancien, et seulement les exercices clos en 2025 ou après ; `null` sans SIREN, sans comptes publiés ou sans exercice aussi récent (`finances_masquees: "exercice_ancien"`). Un zéro est un chiffre non publié. **Règle pratique** : pour des contacts avec le contexte de leur entreprise, `/find` sert à cibler et à compter, puis **c'est `/export` qui produit la donnée exploitable**. ## Facturation - **Compter est gratuit, sans limite.** Envoyez `{ "countOnly": true }` (ou `limit: 0`) : la réponse contient `total` et un tableau `leads` vide. **Aucun débit.** - **Récupérer des enregistrements coûte 1 crédit par enregistrement renvoyé** — sur `/find` (hors mode count-only), sur `/people/{id}` et `/companies/{id}`, et sur `/export`. Le débit a lieu **à chaque appel** : redemander les mêmes enregistrements est **re-facturé** (la donnée a pu être rafraîchie entre-temps ; il n'y a pas de registre « déjà payé »). - ⚠️ `limit: 1` n'est **pas** un mode de comptage : il renvoie 1 enregistrement, donc 1 crédit. Pour compter, utilisez `countOnly: true`. - Quota épuisé → **402** `quota_exhausted`, renvoyé **avant** les enregistrements (rien n'est livré, rien n'est débité) ; ce refus n'est pas compté dans le plafond de requêtes du jour. - **Gratuit et non concerné** : la navigation web (session) et l'extension Basile. Seules les clés API externes sont facturées — la skill Claude passant par une clé API, elle est facturée. - **Le serveur MCP est facturé comme une clé API.** Il exige un plan avec accès API (sinon `403 api_plan_required`, ou `403 payment_past_due` si le paiement du renouvellement a échoué) et consomme 1 crédit par enregistrement rendu, exactement comme un appel REST. Seul `basile_count` reste gratuit. Exception : l'enrichissement (payé sur le solde d'enrichissement, voir ci-dessous). - Méthode recommandée : `countOnly` pour cadrer le volume, puis un `/export` ciblé. ## Enrichissement (crédits d'enrichissement) - Trouve l'e-mail et/ou le numéro de n'importe quelle personne, dans Basile ou non : `full_name` (ou `first_name` + `last_name`), `domain` et/ou `company_name` (obligatoire pour l'e-mail), `linkedin_url` (obligatoire pour le numéro), `find` = `email` (défaut) | `phone` | `both`. - Prix : **5 centimes par e-mail trouvé, 50 centimes par numéro trouvé, rien si rien n'est trouvé**, rien pour une coordonnée déjà possédée. Payé sur le solde d'enrichissement (`GET /enrichment/wallet` : solde, prix, lien de recharge), jamais sur les crédits de recherche ni le quota d'export. - Deux étapes : `POST /enrichment/find` rend tout de suite un `id` (202) ; `GET /enrichment/find/{id}` toutes les 3 s tant que `status` vaut `pending`, puis 200 et `status: completed`. Par canal : `found` (`value`, `verified`), `not_found`, `failed`, `skipped`, `insufficient_balance` ; rien n'est débité hors `found`. `"wait": true` fait attendre le serveur jusqu'à ~25 s. - Idempotence : même `request_id` (ou `Idempotency-Key`) = même demande, rien relancé ni refacturé ; réutilisé pour une autre demande = `409 request_id_conflict`. `person_id` (l'`_id` de `/people/find`) range le résultat sur la fiche Basile du compte. - Envoi groupé : `POST /enrichment/find/batch` (`people`, 100 au plus, `ref` par personne) puis `GET /enrichment/find/batch/{batch_id}`. - Aucune limite par minute ni par jour, hors des limites du forfait : une file fait patienter (`stage: queued`). Plafond de sécurité seulement : 50 000 recherches en file par compte, 50 requêtes/s → `429` (`enrichment_queue_full`) avec `Retry-After`. Solde insuffisant → `402 wallet_insufficient` (`missing_cents`, `topup_url`). - **Clé réservée à l'enrichissement** : un compte à crédits d'enrichissement sans forfait API peut générer une clé qui ne sert qu'à `/enrichment/…` ; toute autre route répond `403 key_enrichment_only` (`upgrade_url`). Avec le forfait API, la même clé ouvre tout. Même règle pour le MCP. ## MCP (serveur distant) - URL : `https://mcp.basile.cc/mcp` (endpoint `POST /mcp`), authentification **OAuth** avec un compte Basile ; aucune clé n'est stockée. - Outils exposés : `basile_count`, `basile_search_people`, `basile_search_companies`, `basile_activity_suggest`, `basile_suggest`, `basile_get_entity`, `basile_export`, `basile_export_status`, et pour l'enrichissement `basile_enrich_person`, `basile_enrichment_status`, `basile_enrichment_balance` (payés sur le solde d'enrichissement ; un compte à crédits sans plan API peut enrichir, pas chercher). - `basile_export` a deux chemins, choisis automatiquement selon le volume. Jusqu'à **500 lignes**, le CSV est renvoyé INLINE dans la conversation. Au-delà, l'outil lance un export FICHIER (construit hors requête, déposé sur S3) et renvoie un `jobId` ; `basile_export_status` rend ensuite un **lien de téléchargement direct valable ~1 h**, avec `truncated` / `quotaReached` s'il y a lieu. Le plafond n'est donc pas 500 lignes mais celui du plan (20 000 lignes par export en plan API, 50 000 en Agence). Le fichier reste récupérable dans l'application web, onglet Exports. - Mêmes filtres, mêmes quotas et même facturation que l'API REST (voir Facturation) : **un plan avec accès API est requis**. ## Règles d'appel qui font échouer une intégration si on les ignore - **Au moins un filtre EFFECTIF est obligatoire** avec une clé d'API, sinon `400 {"error":"At least one filter is required."}`. Ne comptent pas : `filters` vide, `{"include":[]}`, `null`, `""`, une clé inconnue, et `source` seul. La garde s'applique à `/people/find`, `/companies/find`, aux deux `/export` et à `/companies/identifiers`. - **`total` est plafonné à 100 000** sur un `/find` par clé d'API qui renvoie des enregistrements : c'est un PLANCHER, pas le compte réel, et `meta.countCapNotice` le signale. Seul `countOnly: true` rend le compte non plafonné. - **La pagination s'arrête à 250 000 enregistrements par recherche.** Au-delà, `pagination.nextToken` DISPARAÎT sans erreur : une boucle « tant que nextToken » se termine normalement en ayant tronqué l'extraction. Pour un volume supérieur, découpez la recherche (par département, par tranche d'effectif…). - **Plafonds de requêtes par forfait** (par seconde, par minute, par jour ; remise à zéro à minuit UTC) : `api` 5, 100, 2 000 ; `agency` 100, 3 000, 5 000 ; `custom` 100, 3 000, 50 000. Au-delà : `429` (`daily_limit_exceeded` pour le jour, `rate_limit_exceeded` pour la seconde ou la minute) avec `Retry-After`. Les appels d'enrichissement n'y comptent pas, ni un refus `402 quota_exhausted` (au plus autant de refus rendus par jour que le plafond du jour). - **Codes d'erreur** : `400` quatre causes distinguées par `error` (`At least one filter is required.` ; `validation_error` = une valeur illisible nommée dans `message` : ni SIREN ni SIRET, forme juridique ou région inconnue, nombre là où un texte est attendu, `created_since_months` hors de 1, 3, 6, 12, année de création (`creation_date_min`, `creation_date_max`) hors de 1800 à l'année suivante, date invalide ; `too_many_terms` = recherche plus lourde que ce que le moteur accepte en un appel, `message` dit quel filtre découper et combien de valeurs passent, `details` : `filter`, `side`, `values`, `max_values_per_call`, `estimated_terms`, `limit`, `source` ; `invalid_json` = corps qui n'est pas un JSON valide, avec `message` et `messageFr`) · `401` clé absente ou invalide · `402` `quota_exhausted` (crédits mensuels épuisés ; ce refus ne compte pas dans le plafond du jour) ou `export_quota_exhausted` (quota d'export épuisé) ; `subscription_required` et `payment_past_due` (pages > 1) ne concernent que les sessions du site · `403` `api_plan_required` (aucun forfait API actif ; toute requête est refusée, comptage compris), `payment_past_due` (le paiement du renouvellement du forfait API a échoué, abonnement `past_due` ou `unpaid` ; `error` et `code`, `message`, `messageFr`, `billing_url` = page Facturation de l'app ; aucun délai de grâce, l'accès reprend dès que le paiement passe ; même réponse par l'extension) ou `key_enrichment_only` · `413` `payload_too_large` (corps de plus de 1 Mo : découper la demande) · `429` rate limit, avec `Retry-After` · `503` moteur de recherche saturé, avec `Retry-After`. Les 402 de quota ne sont PAS des rate limits : rien à attendre avant la date anniversaire de l'abonnement. - **Plafonds des filtres** : au plus 200 valeurs par côté (`include`, `exclude`) et par filtre, sauf `siren` et les noms d'`employer` entre guillemets (10 000), et `domain` des entreprises (1 000 domaines exacts en inclusion, une carte par domaine ; 10 000 en exclusion ; les débuts de domaine sans point restent à 200) ; `name` des entreprises : 50 noms par appel. Au plus **110 noms complets** (`result_full_name`) par appel, sinon `400 too_many_terms` : découper la liste. Une exclusion de rôle d'un mot de quatre lettres ou plus compte pour un terme, un mot plus court (« RH », « CTO ») jusqu'à 50. `activity`, `region`, `department`, `headquarters_department_code`, `naf_code`, `headquarters_naf_code`, `legal_form` attendent des chaînes (`"75"`, pas `75`). Une clé inconnue est ignorée et listée dans `meta.unknownFilters`. ## Notes de filtrage - Filtre texte = `{ "include": [...], "exclude": [...] }` (include = OR, exclude = NOT) ; plusieurs filtres = ET. - `activity` fonctionne directement sur `/people/find` (secteur de l'entreprise de la personne). - `company_headcount` (plage) fonctionne lui aussi directement sur `/people/find` : c'est la TAILLE de l'entreprise actuelle du contact, multi-source (effectif exact du registre légal + bande déclarée LinkedIn). **N'enchaînez pas `/companies/find` puis `/people/find` pour filtrer par secteur ou par taille** : `activity` et `company_headcount` font les deux en une seule requête. Le détour par les entreprises n'est utile que pour partir d'une liste d'entreprises nommées ou de fiches Google. - ⚠️ Demander `limit: 500` et n'en recevoir que 20 ne coûte rien : la facturation porte sur les enregistrements **renvoyés**, pas demandés. - France : `result_country_code` (people) / `headquarters_country_code` (companies) = `{ "include": ["FR"] }`. - Géographie (entreprises) : `region` prend le NOM (« Auvergne-Rhône-Alpes »), `headquarters_region_code` le code INSEE de région (« 84 », « 11 », « 93 » ; « 1 » vaut « 01 ») ou le nom, `department` le numéro en texte (« 69 », « 2A », « 92: Hauts-de-Seine ») : les trois portent sur les trois sources ; une région inconnue est refusée en 400. `headquarters_department_code` prend le numéro (« 69 ») mais n'existe que sur la source Legal : l'utiliser restreint la recherche au registre. Personnes : `region` (LinkedIn par le département du profil, registre par le code postal de la personne) ; un département ou une région tapé dans `result_city` est appliqué comme tel. - Villes (`result_city`, `headquarters_city`) : graphie libre (tirets, St/Saint, accents), arrondissement (« PARIS 8 ») par son code postal, département ou région tapé dans la ville appliqué comme tel ; `meta.warnings` dit chaque interprétation (`city_as_department`, `city_as_region`, `city_as_postal_code`, `city_homonym`, `city_interpreted`). - `result_role` : intitulé LinkedIn ou mandat du registre, en MOTS ENTIERS (« CTO » ne trouve pas « Director ») ; dans les deux sources, chaque mot avant la première préposition trouve aussi féminin et pluriel (Directeur commercial → Directrice commerciale), un sigle courant (CEO, PDG, DG, DAF, DRH, CTO, COO, CFO…) cherche aussi ses développés ; en exclusion, le dernier mot vaut début de mot. Séniorité et fonction : `current_seniority`, `current_job_functions`. - `currently_in_role: true` (personnes) : en poste aujourd'hui dans les DEUX sources (mandat en cours au registre, poste actuel sur LinkedIn), sans retirer de source ; `result_is_current` ne garde que les dirigeants du registre. - Effectif inconnu : une plage qui part de 0 avec un plafond de 19 au plus (`company_headcount` côté personnes, `headcount_min`/`headcount_max` côté entreprises) garde aussi les fiches sans effectif déclaré (`meta.warnings` `headcount_unknown_included`, avec le nombre) ; `company_headcount_exclude_unknown: true` / `headcount_exclude_unknown: true` les retire (`headcount_unknown_excluded`). - Saisies remises en forme : `siren` (personnes et entreprises) accepte un SIRET (ramené à son SIREN) et plusieurs numéros collés dans une valeur (`siren_normalized`) ; une valeur qui n'est ni l'un ni l'autre : 400. `legal_category` accepte un code INSEE, un sigle (« SAS ») ou un libellé (`legal_form_interpreted`) ; forme inconnue : 400. - Employeur (personnes) : entre guillemets = nom exact ; si aucun employeur ne porte exactement ce nom et que la recherche rend 0, elle est élargie à ses débuts en mots entiers (`employer_exact_relaxed`, `details.exactEmployers`). Au registre, l'employeur est résolu en SIREN (page LinkedIn rattachée, sinon nom exact) et les dirigeants au mandat en cours répondent aussi : 8 employeurs et 20 sociétés par employeur au plus (`employer_registry_partial` au-delà) ; un nom introuvable ou ambigu ne cherche que LinkedIn (`sources_restricted`). Exclure un employeur retire aussi ses dirigeants. - **La société de la ligne** : un résultat de `/people/find` porte `data.context_siren` quand la société affichée diffère de celle qu'on choisirait sans contexte (dirigeant à plusieurs mandats). La repasser en `?siren=` à `GET /people/{id}/full` et dans `company_sirens` (`{ "<_id>": "" }`, avec `ids`) à `POST /people/export` : fiche et fichier montrent alors cette société. - **Une recherche de personnes dans une société qui rend zéro n'est jamais muette** (`/people/find` par clé d'API, `employer` ou `siren`, première page ; en `countOnly`, l'explication seule, sans récupération) : Basile récupère ce qui peut l'être (nom nettoyé en mots entiers, SIREN du registre, page LinkedIn au nom de la société, holding, intitulés de dirigeant ; chaque fiche porte `matchQuality`, seule `employer_approximate` est facturée), sinon `meta.warnings` dit pourquoi, gratuitement et chiffres à l'appui : `company_role_absent`, `company_without_people`, `person_at_other_company`, `company_not_found` (avec les noms proches et leur SIREN), `siren_no_linkedin_company` (aucun SIREN n'a de page LinkedIn, seul le registre répond), `source_incompatible` (bloquant : `source: "LKI"` avec des SIREN sans page LinkedIn, `details.registry_people` = les dirigeants que le registre rendrait). Message anglais dans `message`, français dans `messageFr`. `employerFallback: false` garde le comportement strict. - **Les dirigeants d'un SIREN** (`/people/find` par clé d'API, `siren` + `mandate_role`) : les mandats du registre sont lus même quand la fiche de la personne est rattachée à une autre société, sa SCI ou sa holding (`matchQuality: "registry_mandate"`) ; les holdings sont remontées sur deux niveaux (`registry_holding`, chaîne dans `mandate.via`) ; des profils LinkedIn à titre de dirigeant ne sont proposés que si le registre ne connaît aucun dirigeant en poste (`linkedin_title`, offerts) ; les mandats terminés sont écartés (`registry_mandate_ended`, offerte, pour une fiche rattachée déjà rendue). Chaque fiche porte `mandate` (`label`, `via`, `card_siren`, `card_role`, `unconfirmed`). `mandate_role` accepte les codes et des libellés (« Président », « Directeur général », « DG délégué », PDG, CEO…). Un zéro est expliqué dans `meta.warnings` (`siren_no_known_mandate`, `siren_mandates_ended`, `siren_holding_without_person`…) et n'est pas complété par les récupérations ci-dessus. `registryMandates: false` garde les seules fiches rattachées au SIREN. - `education` : chaque mot saisi commence un mot du nom de l'école ou du diplôme, tous les mots dans la même école (un mot de moins de 4 lettres se cherche en mot entier). `languages` : saisie traduite (« Anglais » = english) puis langue exacte. Au plus 10 valeurs par côté et 2 lettres ou chiffres au moins par valeur, sinon `meta.warnings` : `filter_values_truncated`, `filter_values_ignored`. - Un filtre mono-source ne restreint la recherche à sa source que si TOUS vos filtres mono-source viennent de la même. En combiner de deux sources donne une UNION, pas une intersection : chaque source ne porte que ses propres filtres. Regardez `meta.noticeCode` : `sources_split`, ou `gmb_filter_dropped` quand le filtre Google (note, avis, ouvert le dimanche) a dû être abandonné et n'a donc rien filtré. Côté personnes, `meta.warnings` le dit aussi : `sources_split` (compte de chaque source dans `details.bySource`) ou `sources_restricted` (source retirée par un filtre ; sur un petit résultat, `details.total_without` = le total sans ce filtre). - ⚠️ `/people/find` dont `siren` est le SEUL filtre emprunte un raccourci de lecture directe et ne renvoie que les dirigeants du REGISTRE, pas les salariés LinkedIn — alors que le même appel en `countOnly` compte les deux sources. Ajoutez un second filtre pour obtenir les deux. - ⚠️ Piège de vocabulaire : sur `/people/find`, `with_legal_data` et `with_linkedin_profile` **restreignent la source** (équivalents à `source`). Sur `/companies/find`, `with_legal_data`, `with_linkedin_page`, `with_email` et `with_phone` sont des **filtres ET** : ils gardent les entreprises qui ont AUSSI cette donnée, sans changer les sources interrogées. Même vocabulaire, comportement opposé. - Procédures collectives (`/companies/find` seulement, registre uniquement : en poser un restreint la recherche au registre). Statut calculé sur les jugements publiés au BODACC. `with_procedure` : true = a connu une procédure, en cours ou clôturée (546 592 sociétés) ; false = n'en a jamais connu. `procedure_open` : true = procédure en cours, plans en cours d'exécution compris (168 250, dont 150 544 encore actives) ; false = aucune procédure en cours (garde les sociétés sans procédure ET celles dont la procédure est clôturée). `procedure_type` (include et exclude) : quatre valeurs exactes, `Liquidation judiciaire`, `Redressement judiciaire`, `Procédure de sauvegarde`, `Autre procédure collective` ; avec `procedure_open: true` il porte sur la procédure en cours, sinon sur tout l'historique. Liquidations en cours : `{"filters": {"procedure_open": true, "procedure_type": {"include": ["Liquidation judiciaire"]}}}` (116 310). `procedure_started_after` (date AAAA-MM-JJ, registre seul) : au moins une procédure ouverte à partir de ce jour, close ou en cours, tous types (ouverture de la procédure la plus récente ; une conversion de redressement en liquidation garde la date du redressement). Avec `procedure_open: true`, ouverte depuis ET en cours ; avec `procedure_type`, le type garde sa règle. Date invalide : 400. - Aucun filtre ne distingue un plan d'une période d'observation : lisez `data.procedure_statut.code` dans les résultats (`redressement`, `sauvegarde` = période d'observation ; `plan_redressement`, `plan_sauvegarde` = plan en cours d'exécution ; aussi `liquidation`, `plan_cession`, `cloturee`, `retractee`, `en_cours`), ou la colonne d'export `legal_procedure_situation`. Huit colonnes d'export viennent des jugements : `legal_procedure_situation`, `_situation_depuis`, `_tribunal`, `_organes`, `_cessation_paiements`, `_duree_plan_ans`, `_dernier_jugement`, `_annonce_bodacc`. `GET /companies/{id}/full` renvoie `registre.procedure_statut` et `registre.jugements`. - `company_ceased: false` (« entreprises actives ») ne retire PAS les sociétés en procédure : une liquidation en cours peut être encore active au registre. Pour les écarter, `procedure_open: false`. - Convention collective : `idcc` (`/companies/find`, registre uniquement), code IDCC en chaîne (`"1486"`, `"16"` ; les zéros de tête sont ignorés, `"0016"` vaut `"16"`), jamais l'intitulé. Connue pour 6,4 M sociétés (environ un quart du registre). Export : `legal_convention_idcc`, `legal_convention_nom`. - `created_since_months` (companies) : 1, 3, 6 ou 12 SEULEMENT (autre valeur : 400) ; prend le pas sur `creation_date_min`/`max`, qui acceptent une année ou une date ISO complète ; une année hors de 1800 à l'année suivante : 400 `validation_error` qui nomme le champ. - `with_phone` (companies) désigne un numéro d'ENTREPRISE (fiche Google qui porte un numéro, société du registre ou page LinkedIn dont le domaine a un numéro relevé sur le site ou une fiche Google), jamais le mobile d'une personne. Les trois sources y répondent. - `followers_min` / `followers_max` (companies, LinkedIn seul) : les CONNEXIONS LinkedIn de la société, soit le nombre de profils LinkedIn rattachés à sa page (champ `companies_headcount` de l'index LinkedIn), pas des abonnés ; sous-estime l'effectif réel. À ne pas confondre avec `connection_count` des personnes. - `connection_count` (personnes, LinkedIn seul) : une borne qui ne retient rien (maximum ou minimum à 0 ou moins) est ignorée ; sans borne restante, le filtre disparaît et ne restreint plus la recherche à LinkedIn. `{">": 0}` reste un filtre. - **Zéros expliqués** (entreprises, avertissements informatifs, jamais bloquants, `messageFr` fourni) : `siren_other_filters` (des SIREN demandés existent mais ne passent pas les autres filtres ; `details` : `requested`, `existing`, `other_filters`), `recent_company_contact_data` (téléphone ou email exigé sur des sociétés créées depuis moins de 12 mois, total de 100 au plus : elles en ont rarement ; `details` : `total`, `contact`, `created_since_months` ou `creation_date_min`), `name_relaxed` (un `name` de plusieurs mots qui rend 0 se replie sur ses mots significatifs, « Solabia Group » → « Solabia », sinon sur son premier mot s'il rend 25 sociétés au plus ; `details` : `requested`, `used`, `step`). Propres aux sessions du site : `recent_company_people` (écran « aucun résultat » de « Trouver les contacts » : les dirigeants d'une société créée depuis moins de 12 mois ne sont pas encore publiés) ; les récupérations employeur + nom (`employer_approximate`, `employer_former`, `employer_not_matched`) servent aussi aux sessions du site, avec un texte sans facturation. - `tech_stack` (companies) : registre et LinkedIn, pas Google.