FR
Copied
API

Module registry API

Single source of truth listing every module the platform exposes: active scrapers, meta features, coming-soon items.

Module registry API

The Module registry is the single source of truth listing every module the platform exposes: active scrapers, meta features, and coming-soon items still gathering interest votes. The frontend reads the registry instead of hardcoding module slugs, so adding a module only takes two files (frontend/static/job_types.js and app/job_registry.py).

See also: /docs/concepts/module-registry.

Registry entry shape

Each module is described by a small object that the frontend renders in the dashboard tiles, the search palette, and the pricing pages.

Field Type Purpose
slug string Stable identifier. Used as job_type, route param, and registry key.
category string Group bucket (sources, enrich, signals, outreach, tools).
label object { "fr": "...", "en": "..." }. Bilingual display name.
needs string[] Upstream artifacts the module consumes (e.g. ["leads"]).
produces string[] Downstream artifacts it emits (e.g. ["emails"]).
pipelinable boolean Whether the module can be chained inside a Pipeline.
coming_soon boolean Listed for interest voting only. No backend execution.
alpha_unavailable boolean Built and listed as active, but frozen during alpha. Its create endpoint returns 503.
alpha_reduced boolean Launchable, shown with a "reduced functionality during the alpha" notice. No server-side block.
api_endpoint string | null Path the dashboard calls to start a run, or null for coming-soon modules.

A module is at most one of coming_soon, alpha_unavailable, or plain active. Active modules have a non-null api_endpoint; coming-soon modules have api_endpoint = null. An alpha_unavailable module is presented as active and keeps a non-null api_endpoint, but that endpoint returns 503 while the alpha freeze is in effect.


GET /api/modules-registry

Public endpoint. Returns the server-side mirror of the JS registry. The response is a flat object with one array per bucket plus a feature_pages mapping that points each active module to its published /features/<slug> sales page (or null if not written yet).

Response: 200 OK

{
  "active": [
    "ads_intelligence", "brand_assets", "dead_check", "delivery_check",
    "emails", "filter", "import", "legal_data", "legal_ids",
    "legal_mentions", "opendata", "pagespeed", "phone_info",
    "phones_extra", "pricing", "reviews", "scrap", "sirene",
    "site_finder", "socials", "sort", "techstack", "verify_emails",
    "viewport_test"
  ],
  "multi_proxy": [
    "dead_check", "emails", "legal_data", "legal_ids", "legal_mentions",
    "phones_extra", "pricing", "reviews", "scrap", "site_finder",
    "socials", "techstack"
  ],
  "parallel": [
    "ads_intelligence", "brand_assets", "delivery_check", "filter",
    "import", "opendata", "pagespeed", "phone_info", "sirene", "sort",
    "verify_emails", "viewport_test"
  ],
  "on_demand": [],
  "meta": ["pipeline", "public_api", "veille"],
  "coming_soon": [
    "ai_personalization", "ai_team_members", "ask_to_ai", "bing_places",
    "chrome_extension", "crm", "directories", "funding", "hiring",
    "integrations", "job_changes", "linkedin", "mobile_phones",
    "natural_filter", "pagesjaunes", "press_monitoring",
    "review_patterns", "seo_data", "tech_adoption", "whatsapp",
    "yelp_tripadvisor"
  ],
  "alpha_unavailable": ["finance"],
  "alpha_reduced": ["verify"],
  "feature_pages": {
    "scrap": "scraper-google-maps-gratuit-export-csv",
    "emails": "email-finder-pro-rgpd-france",
    "ads_intelligence": null
  }
}

The multi_proxy set lists scrapers that share the global VPN pool: only one can run at a time platform-wide. parallel modules use direct HTTP and may run concurrently. Clients that schedule jobs should check both sets to surface "Will queue" warnings.

The on_demand key is kept for compatibility and is always an empty list.


GET /api/features

Returns the caller's interest state plus a global counter per coming-soon feature. The counts include every allowed feature id, even those with zero votes, so the frontend can render Needed (N) labels without a fallback branch.

The list of acceptable feature ids equals coming_soon from the registry, plus a tiny legacy set (company, monitoring, pagespeed) kept around to preserve historic votes.

Response: 200 OK

{
  "voted": ["linkedin", "funding"],
  "counts": {
    "linkedin": 27,
    "funding": 14,
    "hiring": 6,
    "ai_personalization": 3,
    "directories": 0,
    "press_monitoring": 0
  }
}

Specific cause: 401 caller is not authenticated.


POST /api/features/{feature_id}/interest

Records an interest vote for feature_id. The operation is idempotent: a second call by the same user is a no-op. Use DELETE on the same path to retract the vote.

feature_id is validated against the allow-list from the registry (coming-soon ids plus legacy ids). Unknown ids return 404 so the endpoint cannot be used as a write-anywhere KV store.

Request

POST /api/features/linkedin/interest

No body. The user is identified by session.

Response: 204 No Content

Empty body. Re-fetch GET /api/features for the updated counter.

Specific causes: 401 not authenticated; 403 authenticated but not active (pending invite); 404 feature_id does not match the registry allow-list.