Les ventes ne sont pas encore ouvertes. Les tarifs sont indicatifs. Demander un accès pilote

Documentation de l'API

Une API REST simple. Vous envoyez une requête, vous recevez du JSON.

Authentification

Chaque appel demande votre clé API, sauf /v1/sample. Envoyez-la dans l'en-tête X-API-Key, ou dans l'en-tête Authorization: Bearer. Votre clé est dans votre page Compte.

Les clés commencent par eldb_live_. Gardez la vôtre secrète : ne la mettez jamais dans le code d'une page web.

curl https://api.ecommerce-leads-database.com/v1/me \
  -H "X-API-Key: eldb_live_…"

# Ou, au choix :
curl https://api.ecommerce-leads-database.com/v1/me \
  -H "Authorization: Bearer eldb_live_…"

Endpoints

Toutes les URL partent de https://api.ecommerce-leads-database.com.

GET/v1/sample

Échantillon gratuit (sans clé)

Renvoie quelques boutiques : 10 par défaut, 20 au plus. Pour voir la forme des données avant de vous abonner. Ne compte pas dans le quota.

curl "https://api.ecommerce-leads-database.com/v1/sample?limit=10"
GET/v1/me

Votre plan et votre quota

Renvoie votre plan, vos requêtes et boutiques utilisées, vos bases et la date de remise à zéro. Gratuit : ne consomme ni requête ni boutique.

curl https://api.ecommerce-leads-database.com/v1/me \
  -H "X-API-Key: eldb_live_…"

{
  "plan": "api_pro",
  "planLabel": "Pro",
  "requests": { "limit": 25000, "used": … },
  "stores": { "limit": 10000, "used": … },
  "databases": { "slots": 3, "selected": ["shopify", "woocommerce", "prestashop"] },
  "exports": true,
  "resetAt": "…"
}
GET/v1/stores/count

Compter les boutiques

Renvoie le nombre de boutiques qui correspondent aux filtres, et combien ont une fiche Google. Coûte 1 requête et 0 boutique.

Paramètres : platform, tld, country, hasGmb, hasEmail, hasPhone, app, currency, lang, operatorCountry, activeOnly, genericEmailsOnly, includeUnverified, includeAliases, maxChromeRank, mailProvider, dmarcPolicy, trackingId, hasDecisionMaker, hasDecisionMakerEmail

curl "https://api.ecommerce-leads-database.com/v1/stores/count?platform=shopify" \
  -H "X-API-Key: eldb_live_…"

{ "count": 29331, "gmbCount": 6511 }

Chiffres réels pour les boutiques Shopify vérifiées.

GET/v1/stores/search

Chercher des boutiques

Filtre la base et renvoie une page de résultats (items) avec un curseur (nextCursor).

Paramètres : platform, tld, country, minProducts, hasGmb, hasEmail, hasPhone, app, currency, lang, operatorCountry, activeOnly, genericEmailsOnly, includeUnverified, includeAliases, maxChromeRank, mailProvider, dmarcPolicy, trackingId, hasDecisionMaker, hasDecisionMakerEmail, cursor, limit

  • limit : de 1 à 100 résultats par page. 50 par défaut.
  • Tri : du plus fort trafic au plus faible. Les boutiques sans trafic connu arrivent en dernier.
  • Par défaut, search et count ne renvoient que les boutiques vérifiées : une vraie boutique en ligne, revérifiée sur son site. Ajoutez includeUnverified=true pour inclure aussi les sites vitrines et les sites injoignables.
  • activeOnly vaut true par défaut : les boutiques notées inactives sont exclues. Ajoutez activeOnly=false pour les inclure.
  • Filtres : hasEmail (email collecté dans les 12 derniers mois), hasPhone, app (une app détectée, ex. Klaviyo), currency (EUR), lang (fr), operatorCountry (FR), genericEmailsOnly (avec hasEmail : adresses génériques seulement). Une valeur invalide renvoie 400 invalid_parameter et la requête n'est pas décomptée.
  • maxChromeRank (palier maximal du classement Chrome UX Report : 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000, 10000000 ou 50000000). Toute autre valeur renvoie 400 invalid_parameter. Le champ audience contient des données du Chrome UX Report (Google), sous licence CC BY-SA 4.0.
  • mailProvider (fournisseur de messagerie déduit du MX : google-workspace, microsoft-365, ovh, infomaniak, ionos, gandi, zoho, proton, o2switch, hostinger, other, none) et dmarcPolicy (none, quarantine, reject ou missing). Toute autre valeur renvoie 400 invalid_parameter. Le filtre app trouve aussi les outils lus dans le DNS (par exemple Klaviyo via SPF). Slugs d'apps que le DNS peut ajouter : klaviyo, mailchimp, brevo, shopify email, mailjet, sendgrid, hubspot, salesforce marketing cloud, omnisend, mandrill, amazon ses, zendesk, mailgun, meta business, google site verification, pinterest, apple, atlassian, zoom, stripe, shopify.
  • Codes de suivi publics : utilisez trackingId pour retrouver les autres boutiques qui partagent un même code. Passez une valeur seule comme GTM-ABC123, AW-123456789, G-ABCDEF1234, UA-1234567-1 ou ca-pub-1234567890123456. Les codes numériques demandent leur type devant : meta:123456789012345, tiktok:…, pinterest:…, microsoftAds:…, linkedin:…, hotjar:…, criteo:…, snapchat:…, clarity:…, klaviyo:… (Klaviyo distingue majuscules et minuscules). Toute autre valeur renvoie 400 invalid_parameter. Chaque résultat contient aussi trackingIds (null tant que la boutique n'a pas été lue).
  • hasDecisionMaker=true|false (au moins un dirigeant connu, ou aucun) et hasDecisionMakerEmail=true (au moins un dirigeant dont l'email a été trouvé sur le site ou validé par le serveur de messagerie). Toute autre valeur renvoie 400 invalid_parameter. Chaque résultat contient aussi hasDecisionMaker.
  • Page suivante : renvoyez la valeur de nextCursor dans le paramètre cursor. À la dernière page, nextCursor vaut null.
  • Chaque boutique renvoyée compte dans votre budget boutiques. Une page de 50 résultats consomme 50 boutiques.
  • Chaque résultat est un résumé de boutique : domaine, plateforme, pays, thème, nombre de produits, apps, trafic, nom du marchand, note et catégorie Google, hasEmail, hasPhone, hasDecisionMaker, currency, lang, operatorCountry, isActiveShop. Chaque résultat contient aussi audience (null si la boutique n'est pas dans le classement Chrome UX Report). Chaque résultat contient aussi dns (null tant que la boutique n'a pas été lue). Pour la fiche complète, appelez /v1/stores/:domain.
curl -G https://api.ecommerce-leads-database.com/v1/stores/search \
  -H "X-API-Key: eldb_live_…" \
  -d platform=shopify \
  -d minProducts=50 \
  -d hasGmb=true \
  -d limit=50

{
  "items": [
    { "domain": "…", "platform": "shopify", "productCount": …, "merchantName": "…", … }
  ],
  "nextCursor": "18450:01J…"
}
GET/v1/stores/:domain

Fiche d'une boutique

Renvoie la fiche complète d'une boutique. Coûte 1 requête et 1 boutique. Le catalogue n'est pas inclus : utilisez /catalog. Chaque email est renvoyé avec son type ; ajoutez genericEmailsOnly=true pour ne recevoir que les adresses génériques. genericEmailsOnly=true masque aussi les emails des dirigeants.

ChampContenu
domainNom de domaine de la boutique.
platformPlateforme e-commerce détectée (shopify, woocommerce…).
tldExtension du domaine.
countryPays (code ISO).
themeThème détecté.
productCountNombre de produits détectés.
verificationStatusRésultat du dernier contrôle du site.
lastSuccessAtDate du dernier contrôle réussi.
firstSeenAtDate d'entrée de la boutique dans la base.
detectedAppsApplications et outils détectés sur le site.
trafficEstimation du trafic mensuel et des mots-clés organiques.
audienceAudience Chrome : { chromeRank, class, country, month, source }. chromeRank est le palier du classement Chrome UX Report (Google) pour ce pays : 1000, 5000, 10000… jusqu'à 50000000. null si la boutique n'est pas classée. Ce champ est partagé sous licence CC BY-SA 4.0 : citez la source et gardez la même licence. Valeurs de class : top_1k, top_5k, top_10k, top_50k, top_100k, top_500k, top_1m, top_5m, top_10m, top_50m. Source du Chrome UX Report : https://developer.chrome.com/docs/crux. Licence : https://creativecommons.org/licenses/by-sa/4.0/. Données adaptées : rangs rapprochés des boutiques et regroupés par pays par nos soins.
dnsDNS : { mailProvider, dmarcPolicy, apps, checkedAt }. mailProvider est le fournisseur de messagerie déduit du MX (google-workspace, microsoft-365, ovh, infomaniak, ionos, gandi, zoho, proton, o2switch, hostinger, other, none). dmarcPolicy vaut none, quarantine, reject ou missing (aucun enregistrement). apps liste les outils d'envoi d'emails et de vérification de domaine lus dans les enregistrements SPF et TXT. checkedAt est la date de la lecture. null tant que la boutique n'a pas été lue. Aucun jeton de vérification n'est exposé.
trackingIdstrackingIds : codes de suivi et de publicité publics (Google Ads, Meta, TikTok…) regroupés par type, par exemple { "gtm": ["GTM-ABC123"], "googleAds": ["AW-123456789"], "meta": ["123456789012345"] }. Types : ga4, ua, gtm, googleAds, floodlight, adsense, meta, tiktok, pinterest, microsoftAds, linkedin, snapchat, criteo, clarity, hotjar, klaviyo. {} si rien n'a été trouvé, null tant que la boutique n'a pas été lue. Seuls les codes que tout visiteur peut voir dans le code source de la page.
platformVersionVersion de la plateforme (PrestaShop, Magento, Odoo) quand le site l'affiche.
operatorPays de l'entreprise derrière la boutique ({ country, source }) : d'après son numéro de TVA, les réglages Shopify, l'adresse des mentions légales, le téléphone ou l'extension, dans cet ordre. Peut différer de l'extension.
isActiveShopfalse quand la boutique semble inactive (catalogue vide, produits de démo, devise par défaut), avec les raisons dans activeShopReasons. null tant qu'elle n'est pas notée.
legalPage de mentions légales : pageUrl, companyIds (SIREN, TVA, numéro d'entreprise BE, IDE CH, vérifiés par leur clé), legalForm.
shopifyBoutiques Shopify : shopId, isPlus, shipsToCountries, shopPayInstallments, collectionsCount, themeStoreId.
catalogStatsChiffres du catalogue quand la plateforme les expose : prix et poids moyens, variantes, images, marques, types de produits, catégories, date du dernier produit.
metadatamerchantName ; contactEmail avec contactEmailType (generic, personal ou unknown) et emailDomainMatch ; telephone (E.164) avec phoneType (mobile, fixed_line…) ; address ; socialLinks ; sources (page et date de collecte de chaque contact) ; title, metaDescription, lang, currency, hreflangs, features, paymentMethods, shippingCarriers, salesChannels, copyrightYear, contactPageUrl, canonicalUrl. Un contact collecté il y a plus de 12 mois, ou un email dont le titulaire s'est opposé, vaut null avec la raison dans contactEmailWithheld, telephoneWithheld ou addressWithheld.
emailsTous les emails publiés par la boutique : [{ email, type, sourceUrl }]. type vaut generic, personal ou unknown ; sourceUrl est la page où l'email a été lu. 10 au plus, le meilleur d'abord. Un email lu il y a plus de 12 mois, ou retiré par son titulaire, n'est pas renvoyé. Avec genericEmailsOnly=true, seuls les emails generic restent.
decisionMakersDirigeants : [{ firstName, lastName, role, source, sourceUrl, since, email, emailStatus }], le dirigeant principal d'abord. role : owner (propriétaire, entrepreneur individuel), president, managing_director (directeur général), manager (gérant), publication_director (directeur de la publication), partner (associé), administrator (administrateur), other. source : rne (registre national des entreprises, France), zefix (registre du commerce, Suisse) ou legal_page (mentions légales de la boutique). sourceUrl : la fiche publique de l'entreprise dans le registre, ou la page de mentions légales. since : date d'entrée en fonction quand le registre la donne, sinon null. emailStatus : found_on_site (adresse publiée sur le site), valid (acceptée par le serveur de messagerie du domaine), catch_all (le serveur accepte toutes les adresses : format le plus probable, non confirmé), pattern (déduite du format d'adresse du domaine, non vérifiée), not_found (aucune adresse acceptée par le serveur), null (aucune adresse connue). email vaut null si l'adresse a été retirée par son titulaire, si elle date de plus de 12 mois, ou avec genericEmailsOnly=true. Un dirigeant lu il y a plus de 12 mois n'est plus renvoyé. Jamais de date de naissance, de nationalité ni d'adresse personnelle.
companyFiche du registre des entreprises : { registry, registryId, officialName, activityCode, headcountBand, createdOn, category, legalFormCode, active, hq, checkedAt }. registry vaut fr, be ou ch ; registryId est le SIREN, le numéro d'entreprise BE ou l'IDE CH. officialName : dénomination officielle. activityCode : code d'activité (NAF ou NACE). headcountBand : tranche d'effectif salarié, par exemple "10-19". createdOn : date de création. category : catégorie d'entreprise (France). legalFormCode : code de forme juridique du registre. active : false si l'entreprise est fermée. hq : code postal et commune du siège. checkedAt : date de la dernière lecture du registre. Un champ que le registre ne donne pas vaut null. company vaut null si la boutique n'a pas d'identifiant d'entreprise, si le registre ne la connaît pas, ou si la lecture date de plus de 12 mois.
gmbFiche Google : placeId, category, additionalCategories, rating, ratingDistribution, isClaimed, totalPhotos, workTime, address, addressInfo, latitude, longitude, phone, website. null s'il n'y en a pas.
curl https://api.ecommerce-leads-database.com/v1/stores/probikeshop.fr \
  -H "X-API-Key: eldb_live_…"

{
  "store": {
    "domain": "probikeshop.fr",
    "platform": "shopify",
    "tld": "fr",
    "country": "FR",
    "theme": "…",
    "productCount": 5000,
    "verificationStatus": "…",
    "lastSuccessAt": "…",
    "detectedApps": ["…"],
    "trackingIds": { "gtm": ["GTM-ABC123"], "googleAds": ["AW-123456789"] },
    "operator": { "country": "FR", "source": "vat" },
    "isActiveShop": true,
    "legal": { "pageUrl": "…", "companyIds": { "siren": "…", "vat": "…" }, "legalForm": "SAS" },
    "metadata": {
      "merchantName": "…",
      "contactEmail": "…",
      "contactEmailType": "generic",
      "contactEmailWithheld": null,
      "telephone": "+33…",
      "phoneType": "fixed_line",
      "address": { … },
      "sources": {
        "contactEmail": { "url": "https://…/mentions-legales", "at": "2026-10-19T08:00:00.000Z" }
      },
      "socialLinks": { "instagram": "…" },
      "currency": "EUR",
      "lang": "fr"
    },
    "emails": [
      { "email": "contact@…", "type": "generic", "sourceUrl": "https://…/contact" }
    ],
    "decisionMakers": [
      {
        "firstName": "Marie", "lastName": "Durand", "role": "president",
        "source": "rne", "sourceUrl": "https://annuaire-entreprises.data.gouv.fr/entreprise/…",
        "since": "2019-03-01", "email": "marie.durand@…", "emailStatus": "valid"
      }
    ],
    "company": {
      "registry": "fr", "registryId": "…", "officialName": "…",
      "activityCode": "47.91B", "headcountBand": "10-19", "createdOn": "…",
      "category": "PME", "legalFormCode": "5710", "active": true,
      "hq": "…", "checkedAt": "…"
    },
    "gmb": {
      "placeId": "…", "category": "…", "rating": 4.5, "votes": 594,
      "address": "…", "phone": "…", "website": "…"
    }
  }
}
GET/v1/stores/:domain/catalogPro et Scale

Catalogue produits

Renvoie les produits de la boutique, 5 000 au plus. Disponible pour une partie des boutiques Shopify et WooCommerce. Sinon, erreur 404 no_catalog, non facturée. Coûte 10 requêtes.

curl https://api.ecommerce-leads-database.com/v1/stores/probikeshop.fr/catalog \
  -H "X-API-Key: eldb_live_…"

{
  "domain": "probikeshop.fr",
  "catalog": [
    {
      "id": "…", "title": "…", "handle": "…", "vendor": "…",
      "productType": "…", "tags": ["…"],
      "price": …, "compareAtPrice": …, "currency": "EUR",
      "available": true, "imageUrl": "…", "imageCount": …, "variantCount": …,
      "createdAt": "…", "updatedAt": "…"
    }
  ]
}
GET/v1/stores/:domain/trendPro et Scale

Tendance de trafic

Renvoie l'historique mensuel du trafic organique et des positions. Erreur 404 no_trend s'il n'y a pas de données, non facturée. Coûte 2 requêtes.

curl https://api.ecommerce-leads-database.com/v1/stores/probikeshop.fr/trend \
  -H "X-API-Key: eldb_live_…"

{
  "domain": "probikeshop.fr",
  "trend": [
    { "date": "2026-07-01", "organicTraffic": 197021, "organicPositions": 19377 }
  ],
  "savedAt": "2026-07-01T04:12:08.441Z"
}

Enrichir avec vos clés

Trouvez l'email et le téléphone des dirigeants d'une boutique avec votre propre compte Apollo, FullEnrich, Kaspr ou Dropcontact. L'appel utilise vos crédits chez le fournisseur. Les résultats sont à vous : aucun autre client ne les voit.

Enregistrez vos clés de fournisseur dans votre compte, page Mes clés de fournisseurs. Elles ne passent jamais par l'API : une clé ELDB volée ne permet ni de les lire ni de les changer.

Par demande : 25 boutiques et 3 dirigeants par boutique. Par client : 3 enrichissements en cours, et 500 personnes par fournisseur et par jour (UTC). Un résultat est servi 12 mois, puis effacé à 13 mois.

GET/v1/enrichment/providers

Vos fournisseurs

Liste les fournisseurs dont la clé est enregistrée, avec leur statut et les crédits restants quand le fournisseur les donne. Gratuit.

curl https://api.ecommerce-leads-database.com/v1/enrichment/providers \
  -H "X-API-Key: eldb_live_…"

{
  "providers": [
    { "provider": "dropcontact", "status": "valid", "creditsRemaining": 250 }
  ]
}
POST/v1/enrichments

Lancer un enrichissement

Envoyez provider et domain (une boutique) ou domains (25 au plus). maxPeoplePerStore : de 1 à 3, 2 par défaut. phones : true pour demander aussi les téléphones (plus de crédits). force : true pour relancer une personne enrichie il y a moins de 30 jours. Coûte 1 requête et 1 boutique par boutique qui a des dirigeants. Réponse 200 avec les résultats quand le fournisseur répond tout de suite, sinon 202 : suivez le job.

curl -X POST https://api.ecommerce-leads-database.com/v1/enrichments \
  -H "X-API-Key: eldb_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "provider": "dropcontact", "domains": ["probikeshop.fr"], "maxPeoplePerStore": 2 }'

HTTP/1.1 202 Accepted
{
  "job": {
    "id": "…", "provider": "dropcontact", "status": "queued", "phones": false,
    "storeCount": 1, "personCount": 2, "creditsUsed": null, "errorCode": null,
    "createdAt": "…", "updatedAt": "…"
  },
  "results": [
    { "domain": "probikeshop.fr", "status": "ok", "people": [ … ] }
  ]
}
GET/v1/enrichments/:jobId

Suivre un enrichissement

Renvoie le statut du job (queued, submitted, done, partial, failed, canceled) et les résultats par boutique. Gratuit. Attendez au moins 20 secondes entre deux appels.

curl https://api.ecommerce-leads-database.com/v1/enrichments/<jobId> \
  -H "X-API-Key: eldb_live_…"
GET/v1/stores/:domain/enrichment

Résultats d'une boutique

Renvoie la plateforme, le nom du marchand, les dirigeants, vos fournisseurs et vos résultats. Coûte 1 requête et 1 boutique. DELETE sur la même URL efface vos résultats pour cette boutique.

curl https://api.ecommerce-leads-database.com/v1/stores/probikeshop.fr/enrichment \
  -H "X-API-Key: eldb_live_…"

{
  "domain": "probikeshop.fr",
  "platform": "…",
  "merchantName": "…",
  "providers": ["dropcontact"],
  "decisionMakers": [{ "firstName": "…", "lastName": "…", "role": "president" }],
  "results": [
    {
      "firstName": "…", "lastName": "…", "role": "president", "provider": "dropcontact",
      "status": "found", "skipReason": null,
      "email": "…", "emailStatus": "valid", "emailStatusRaw": "nominative@pro", "emailKind": "professional",
      "phone": null, "phoneType": null, "linkedinUrl": "…", "jobTitle": "…",
      "creditsUsed": 1, "errorCode": null, "enrichedAt": "…", "reused": false
    }
  ]
}

Chaque résultat contient firstName, lastName, role, provider, status (pending, found, not_found, skipped, error), skipReason, email, emailStatus (valid, risky, catch_all, invalid, unknown), emailStatusRaw (le libellé du fournisseur), emailKind (professional, generic, personal), phone, phoneType, linkedinUrl, jobTitle, creditsUsed, errorCode, enrichedAt et reused (true : résultat déjà obtenu, sans nouveaux crédits).

GET /v1/stores/:domain renvoie aussi enrichment : vos propres résultats pour cette boutique, à côté de decisionMakers. Tableau vide si vous n'en avez pas.

Quotas et coûts

Chaque plan a deux compteurs : les requêtes et les boutiques. Ils repartent à zéro à chaque renouvellement de votre abonnement.

Nous vous envoyons un email quand vous avez utilisé 80 % d'un compteur.

Le budget boutiques compte chaque boutique renvoyée par /v1/stores/search, et 1 boutique par appel à /v1/stores/:domain. /v1/stores/count et /v1/me ne consomment pas de boutiques.

Les erreurs 404, 403 et 409 ne sont pas facturées.

EndpointRequêtesBoutiques
/v1/sample00
/v1/me00
/v1/stores/count10
/v1/stores/search11 par boutique renvoyée
/v1/stores/:domain11
/v1/stores/:domain/catalog100
/v1/stores/:domain/trend20
/v1/enrichment/providers00
POST /v1/enrichments11 par boutique avec dirigeants
/v1/enrichments/:jobId00
/v1/stores/:domain/enrichment11

En-têtes de réponse

Erreurs

Une erreur renvoie un code HTTP et un JSON avec un champ error.

HTTPCodeSignification
400invalid_parameterUn paramètre est invalide, par exemple limit hors de 1 à 100.
401missing_api_keyAucune clé envoyée.
401invalid_api_keyClé inconnue ou révoquée.
402active_subscription_requiredPas d'abonnement actif sur ce compte.
402plan_upgrade_requiredEndpoint absent de votre plan (reason : exports_not_in_plan). Catalogue et tendances demandent Pro ou Scale.
403plan_restrictionPlateforme hors de vos bases (reason : platform_locked). Le champ allowed liste vos bases.
404not_foundDomaine inconnu.
404no_catalogPas de catalogue pour cette boutique.
404no_trendPas de tendance pour cette boutique.
409no_database_selectedChoisissez d'abord vos bases dans votre compte.
429quota_exceededQuota de requêtes épuisé jusqu'à resetAt.
429store_quota_exceededBudget boutiques épuisé jusqu'à resetAt.
429rate_limitedTrop d'appels en peu de temps. Attendez le délai de l'en-tête Retry-After.
429platform_change_limitedChangement de base limité à 1 tous les 30 jours.
400too_many_storesPlus de 25 boutiques dans un enrichissement.
402provider_out_of_creditsVotre compte chez le fournisseur n'a plus de crédits.
404provider_not_availableCe fournisseur n'est pas ouvert à l'enrichissement.
409provider_key_missingAucune clé enregistrée pour ce fournisseur.
422provider_key_invalidLe fournisseur a refusé votre clé. Remplacez-la dans votre compte.
422provider_plan_has_no_apiVotre offre chez le fournisseur ne donne pas accès à l'API.
429byok_open_jobs3 enrichissements tournent déjà. Attendez qu'un se termine.
429byok_daily_cap500 personnes envoyées aujourd'hui à ce fournisseur. Réessayez demain.
429provider_rate_limitedLe fournisseur demande de ralentir. Le job reprend tout seul.
502provider_unavailableLe fournisseur ne répond pas. Le job réessaie tout seul.
503opt_out_unavailablePause de quelques minutes : la vérification des oppositions ne répond pas. Rien n'est envoyé.

Exemple de réponse quand le budget boutiques est épuisé :

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 25000
X-RateLimit-Remaining: 0
X-Stores-Limit: 10000
X-Stores-Remaining: 0

{
  "error": "store_quota_exceeded",
  "plan": "api_pro",
  "quotaMonthly": 25000,
  "quotaUsed": …,
  "storesMonthly": 10000,
  "storesUsed": 10000,
  "resetAt": "…"
}

Serveur MCP

Branchez votre agent IA (Claude, Cursor…) sur la base. Même clé, mêmes quotas. Le serveur propose 8 outils :

Claude Code

claude mcp add eldb --transport http https://mcp.ecommerce-leads-database.com/mcp \
  --header "X-API-Key: eldb_live_…"

Cursor et clients compatibles (JSON)

Pour un client qui accepte un serveur HTTP distant avec en-têtes, comme Cursor (fichier mcp.json) :

{
  "mcpServers": {
    "eldb": {
      "url": "https://mcp.ecommerce-leads-database.com/mcp",
      "headers": {
        "Authorization": "Bearer eldb_live_…"
      }
    }
  }
}

Claude Desktop : passez par le pont mcp-remote, dans claude_desktop_config.json :

{
  "mcpServers": {
    "eldb": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://mcp.ecommerce-leads-database.com/mcp",
        "--header", "Authorization: Bearer eldb_live_…"
      ]
    }
  }
}

La clé passe toujours dans un en-tête. Ne la mettez jamais dans l'URL.

Exemples de code

Lister toutes les boutiques Shopify qui ont une fiche Google, page par page.

JavaScript (fetch)

const API = "https://api.ecommerce-leads-database.com";
const headers = { "X-API-Key": process.env.ELDB_API_KEY };

let cursor = null;
do {
  const url = new URL("/v1/stores/search", API);
  url.searchParams.set("platform", "shopify");
  url.searchParams.set("hasGmb", "true");
  url.searchParams.set("limit", "50");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, { headers });
  if (res.status === 429) {
    console.log(await res.json()); // quota ou budget épuisé : voir resetAt
    break;
  }
  if (!res.ok) throw new Error(`HTTP ${res.status}`);

  const { items, nextCursor } = await res.json();
  for (const store of items) console.log(store.domain);
  console.log("Boutiques restantes :", res.headers.get("X-Stores-Remaining"));
  cursor = nextCursor;
} while (cursor);

Python (requests)

import os
import requests

API = "https://api.ecommerce-leads-database.com"
headers = {"X-API-Key": os.environ["ELDB_API_KEY"]}
params = {"platform": "shopify", "hasGmb": "true", "limit": 50}

while True:
    r = requests.get(f"{API}/v1/stores/search", headers=headers, params=params)
    if r.status_code == 429:
        print(r.json())  # quota ou budget épuisé : voir resetAt
        break
    r.raise_for_status()
    data = r.json()
    for store in data["items"]:
        print(store["domain"])
    print("Boutiques restantes :", r.headers.get("X-Stores-Remaining"))
    if not data["nextCursor"]:
        break
    params["cursor"] = data["nextCursor"]