API Recon IA
Documentation complète de tous les endpoints REST, outils OSINT et flux d'intégration de la plateforme de reconnaissance passive.
Introduction
Vue d'ensemble de l'API Recon IA
Recon IA expose une API REST JSON qui permet d'effectuer de la reconnaissance passive sur des domaines cibles. Toutes les réponses suivent une enveloppe standardisée.
L'API est exposée sur le port
8080 du serveur. Exemple : https://api.idachallenge.bjFormat de réponse standardisé
{
"success": true,
"data": { /* objet ou tableau */ },
"message": "Opération réussie"
}
{
"success": false,
"error": "Description de l'erreur"
}
Authentification
HTTP Basic Auth sur tous les endpoints protégés
Les endpoints sensibles requièrent une authentification HTTP Basic Auth (Base64 de email:mot_de_passe). Un endpoint POST /auth/login permet de valider les credentials avant d'effectuer des appels.
ADMIN_EMAIL et ADMIN_PASSWORD_HASH) sont définis dans le fichier .env. Ne les exposez jamais dans le code ou les logs.Exemple d'en-tête Authorization
Authorization: Basic base64(email:password) # Exemple avec cURL : curl -u "admin@example.com:monmotdepasse" \ -X POST https://api.idachallenge.bj/pass_recon \ -H "Content-Type: application/json" \ -d '{"domain": "example.com"}'
Rate Limiting
Limites de débit par endpoint
| Endpoint | Limite | Scope |
|---|---|---|
POST /auth/login | 10 / minute | Par IP |
POST /recon | 20 / heure | Par IP |
POST /pass_recon | 10 / heure | Par IP |
Autres endpoints | Défaut global | Par IP |
HTTP 429 Too Many Requests.Codes d'erreur HTTP
Codes de statut renvoyés par l'API
Endpoints
Référence complète de tous les endpoints disponibles
Valide les identifiants administrateur (email + mot de passe). Endpoint public — aucune authentification préalable requise.
Corps de la requête
| Champ | Type | Statut | Description |
|---|---|---|---|
| string | requis | Email administrateur | |
| password | string | requis | Mot de passe en clair (comparé via hash bcrypt) |
Exemple
curl -X POST https://api.idachallenge.bj/auth/login \ -H "Content-Type: application/json" \ -d '{"email": "admin@example.com", "password": "motdepasse"}'
Réponses
{"success": true, "message": "Authentification réussie."}Crée un enregistrement de reconnaissance. Un code OTP à 6 chiffres est envoyé à l'email fourni. L'enregistrement est inactif jusqu'à la validation OTP.
Corps de la requête
| Champ | Type | Statut | Description |
|---|---|---|---|
| domain | string | requis | Nom de domaine cible (ex: example.com) |
| string | requis | Email pour recevoir le code OTP et les résultats | |
| full_name | string | optionnel | Nom complet du demandeur |
| organization | string | optionnel | Organisation |
Exemple
curl -X POST https://api.idachallenge.bj/recon \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "email": "vous@example.com", "full_name": "Jean Dupont" }'
Réponses
Active l'enregistrement de reconnaissance en validant le code OTP à 6 chiffres reçu par email.
Corps de la requête
| Champ | Type | Statut | Description |
|---|---|---|---|
| string | requis | Email utilisé lors de la création | |
| code | string | requis | Code OTP à 6 chiffres reçu par email |
Réponses
Retourne la liste paginée de tous les enregistrements de reconnaissance. Nécessite HTTP Basic Auth.
Paramètres de query
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| page | integer | 1 | Numéro de page |
| per_page | integer | 20 | Résultats par page (max 100) |
Réponse
{
"success": true,
"data": [ /* tableau d'enregistrements */ ],
"total": 42,
"page": 1,
"per_page": 20,
"pages": 3
}
Retourne les informations d'un enregistrement sans les données sensibles (email masqué).
Réponses
Met à jour les champs d'identité d'un enregistrement (full_name, organization, status).
Réponses
Supprime définitivement un enregistrement et toutes ses données associées.
Réponses
Lance une reconnaissance passive complète sur un domaine. Exécute jusqu'à 20+ outils OSINT en parallèle. Résultats mis en cache pendant 24h.
Corps de la requête
| Champ | Type | Statut | Description |
|---|---|---|---|
| domain | string | requis | Nom de domaine à analyser (ex: example.com) |
| tools | array | optionnel | Liste des outils à exécuter. Défaut: tous les outils |
| force | boolean | optionnel | Forcer un nouveau scan même si en cache (false) |
Outils disponibles pour le champ tools
[ /* DNS & IP */ "dns_records", "ip_info", "asn_info", "ptr_records", "reverse_ip", "dnsbl_check", /* SSL / TLS */ "ssl_info", "tls_config", /* Sous-domaines */ "amass", "subfinder", "assetfinder", "crtsh", "github", /* HTTP & Web */ "http_methods", "redirect_chain", "robots_txt", "security_headers", "tech_stack", "waf_detection", "favicon_hash", "archive_history", /* Email & WHOIS */ "email_config", "whois_info", /* Sécurité */ "subdomain_takeover" ]
Exemple — scan sélectif
curl -u "admin@example.com:password" \ -X POST https://api.idachallenge.bj/pass_recon \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "tools": ["dns_records", "ssl_info", "security_headers"] }'
Réponses
Lance un crawl web passif sur une URL avec l'outil creepyCrawler. Les IP privées et les domaines locaux sont bloqués (protection SSRF).
Corps de la requête
| Champ | Type | Statut | Description |
|---|---|---|---|
| url | string (uri) | requis | URL à crawler (http:// ou https:// uniquement) |
| options | array | optionnel | Options creepyCrawler (voir liste ci-dessous) |
Options autorisées
--depth Profondeur de crawl --threads Nombre de threads parallèles --timeout Timeout par requête (secondes) --delay Délai entre requêtes (secondes) --max-urls Nombre maximum d'URLs à crawler --verbose Mode verbeux --silent Mode silencieux
Interroge la base de données publique crt.sh pour lister tous les certificats SSL/TLS émis pour un domaine et ses sous-domaines.
Corps
| Champ | Type | Statut |
|---|---|---|
| domain | string | requis |
Résout tous les types d'enregistrements DNS (A, AAAA, MX, TXT, NS, CNAME, SOA) pour un domaine.
Corps
| Champ | Type | Statut |
|---|---|---|
| domain | string | requis |
Lance sslscan pour analyser les protocoles TLS supportés, les suites de chiffrement, les certificats et les vulnérabilités SSL (HEARTBLEED, POODLE, etc.).
Corps
| Champ | Type | Statut |
|---|---|---|
| host | string | requis |
Utilise holehe pour vérifier si une adresse email est associée à un compte sur diverses plateformes en ligne (Google, Twitter, GitHub, etc.).
Corps
| Champ | Type | Statut |
|---|---|---|
| string | requis |
Utilise Sublist3r pour énumérer les sous-domaines via des moteurs de recherche publics et des sources OSINT.
Corps
| Champ | Type | Statut |
|---|---|---|
| domain | string | requis |
Scrape le rapport Netcraft pour un domaine : technologies détectées, historique d'hébergement, informations réseau et indicateurs de risque.
Corps
| Champ | Type | Statut |
|---|---|---|
| domain | string | requis |
Retourne le journal d'audit de toutes les requêtes HTTP traitées par l'API (méthode, endpoint, code HTTP, durée, IP, user-agent).
Paramètres de query
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| page | integer | 1 | Page |
| per_page | integer | 50 | Entrées par page |
Exécute deux agents IA en parallèle sur les données de /pass_recon :
• Groq (llama-3.3-70b-versatile) — Analyste menaces techniques : CVE actives, exploits, vecteurs d'attaque
• OpenRouter (qwen3-235b:free) — Auditeur exhaustif : couvre toutes les sections OSINT, documente aussi les bonnes pratiques
Les deux rapports sont fusionnés automatiquement : findings dédupliqués, risk_score = max(groq, openrouter), union des forces et actions.
Cache intelligent : si recon_id est fourni et qu'une analyse valide existe en base (non expirée), le résultat est retourné instantanément sans appel IA. La nouvelle analyse fusionnée est automatiquement sauvegardée en BD.
Corps (JSON)
| Champ | Type | Statut | Description |
|---|---|---|---|
| recon_json | object | requis | JSON complet retourné par POST /pass_recon |
| recon_id | integer | optionnel | ID Recon pour activer le cache BD. Si fourni et cache valide → retour instantané sans appel IA |
| force_refresh | boolean | optionnel | Forcer une nouvelle analyse même si le cache est valide (défaut: false) |
| model | string | optionnel | Surcharger le modèle IA (ex: llama-3.1-8b-instant). Défaut: ANALYSIS_MODEL du .env |
| max_search_rounds | integer | optionnel | Nombre max de cycles de recherche web (1–10, défaut : 6) |
Comportement du cache
"cached": trueautomatique en BD
Toujours régénère
Réponse (200)
| Champ | Type | Description |
|---|---|---|
| success | boolean | Statut de la requête |
| cached | boolean | true si retour depuis le cache BD, false si nouvelle analyse |
| data.domain | string | Domaine analysé |
| data.risk_score | integer | Score de risque global 0–100 |
| data.risk_level | string | CRITICAL | HIGH | MEDIUM | LOW |
| data.executive_summary | string | Résumé 3–5 phrases pour un CISO |
| data.findings | array | Vulnérabilités avec severity, evidence (données OSINT exactes), references (CVE/CWE/OWASP), web_sources |
| data.attack_surface | object | Sous-domaines, services exposés, technologies, hébergeurs |
| data.strengths | array | Bonnes pratiques déjà en place |
| data.immediate_actions | array | Actions prioritaires (P1=urgent, P2=cette semaine, P3=ce mois) |
| data.searches_performed | array | Recherches web effectuées par l'agent IA |
| data.model_used | string | groq+openrouter (merged) si les deux backends ont répondu, sinon le modèle actif |
| data.security_score | integer | Score de sécurité global 0–100 (100 = parfait). Calculé depuis les findings (−25/CRITICAL, −15/HIGH, −8/MEDIUM, −3/LOW) et les strengths (+2 chacun, max +10) |
| data.security_grade | string | Note de sécurité : A+(≥95) / A(≥90) / B+(≥85) / B(≥80) / C+(≥75) / C(≥70) / D+(≥60) / D(≥50) / E(≥35) / F(<35) |
| data.security_posture | string | Appréciation qualitative (ex: "Moyen — plusieurs points de sécurité à corriger") |
| data.security_breakdown | object | Score par catégorie — DNS, SSL, Email, Web, Infrastructure, Subdomain, Reputation, Cloud. Chaque entrée : score, grade, findings_count, critical, high |
| data.findings_summary | object | Comptage des findings : total, critical, high, medium, low, info |
| data._merge_details | object | Détails de la fusion : groq_score, openrouter_score, groq_findings, openrouter_findings, merged_findings, groq_searches, openrouter_searches |
| data._cache | object | generated_at, expires_at, expires_in_h, hit (présent si recon_id fourni) |
Codes d'erreur
| Code | Description |
|---|---|
| 400 | recon_json manquant/invalide ou paramètre model avec caractères interdits |
| 429 | Rate limit dépassé (5 requêtes/heure par IP) |
| 500 | Les deux backends IA ont échoué à produire un rapport (vérifier les logs) |
| 503 | Aucun backend configuré (ni GROQ_API_KEY ni OPENROUTER_API_KEY dans .env) |
Vérifie la disponibilité de chaque backend IA configuré (Groq, OpenRouter, Ollama), indique si l'analyse duale est active, et retourne le fournisseur de recherche web.
Réponse
| Champ | Type | Description |
|---|---|---|
| success | boolean | Au moins un backend est joignable |
| backends_active | array | Liste des backends en ligne (ex: ["groq", "openrouter"]) |
| dual_analysis | boolean | true si Groq ET OpenRouter sont actifs — fusion automatique activée |
| search_provider | string | tavily (si TAVILY_API_KEY défini) ou duckduckgo (gratuit) |
| groq.configured | boolean | GROQ_API_KEY présent dans .env |
| groq.online | boolean | API Groq accessible |
| groq.model | string | Modèle Groq actif (ANALYSIS_MODEL) |
| groq.models | array | Liste des modèles Groq disponibles |
| openrouter.configured | boolean | OPENROUTER_API_KEY présent dans .env |
| openrouter.online | boolean | API OpenRouter accessible |
| openrouter.model | string | Modèle OpenRouter actif (OPENROUTER_MODEL) |
| ollama | object | Statut Ollama (présent uniquement si aucune clé cloud configurée — fallback) |
Condense les données OSINT (scan_results) et l'analyse IA (analysis_result)
stockées en base pour produire un rapport narratif structuré JSON.
Le rapport est enregistré dans recon.final_report et retourné dans la réponse.
Prérequis :
scan_results ET analysis_result doivent être présents en base
(étapes OSINT + analyse IA déjà effectuées).
Modèle IA :
Groq par défaut, OpenRouter en fallback. Appel direct (pas agentique — toutes les données sont déjà disponibles).
Cache :
Si final_report existe déjà en base, retourné immédiatement ("cached": true).
Utiliser force_regenerate: true pour forcer la régénération.
Paramètres URL
| Paramètre | Type | Description |
|---|---|---|
| id | integer | ID de l'enregistrement Recon |
Corps de la requête
| Champ | Type | Requis | Description |
|---|---|---|---|
| force_regenerate | boolean | non | Forcer la régénération même si rapport déjà en BD (défaut : false) |
Structure du rapport généré
Réponse (200)
| Champ | Type | Description |
|---|---|---|
| success | boolean | Génération réussie |
| cached | boolean | true si rapport chargé depuis le cache BD |
| data.domain | string | Domaine analysé |
| data.security_score | integer | Score de sécurité global (0-100) |
| data.security_grade | string | Grade (A+ → F) |
| data.executive_summary | string | Résumé exécutif narratif |
| data.infrastructure_overview | string | Description de l'infrastructure |
| data.key_findings_narrative | string | Narration des findings critiques |
| data.risk_assessment | string | Évaluation du risque et impact business |
| data.prioritized_recommendations | array | Actions correctives prioritaires |
| data.positive_points | array | Points positifs et bonnes pratiques détectés |
| data.conclusion | string | Conclusion avec prochaines étapes |
| data.findings_summary | object | Compteurs par sévérité (CRITICAL/HIGH/MEDIUM/LOW/INFO) |
Codes de réponse
| Code | Description |
|---|---|
| 200 | Rapport généré (ou chargé depuis le cache) et enregistré en BD |
| 400 | scan_results ou analysis_result absent — effectuez d'abord les étapes OSINT + analyse IA |
| 404 | Enregistrement Recon introuvable |
| 429 | Rate limit dépassé (20 requêtes/heure) |
| 500 | Erreur génération IA (modèle indisponible) |
Génère un rapport PDF professionnel (logo vectoriel, couleurs sévérité, métriques), l'enregistre en base de données (pdf_report BYTEA) et l'envoie par email.
Chargement automatique : si analysis est absent du body, il est chargé depuis recon.analysis_result en BD.
Rapport narratif intégré : si recon.final_report existe (généré par POST /generate_final_report), son executive_summary enrichit le PDF.
Flux recommandé : appeler d'abord POST /generate_final_report pour un PDF enrichi du rapport narratif IA.
Paramètres URL
| Paramètre | Type | Description |
|---|---|---|
| id | integer | ID de l'enregistrement Recon |
Corps de la requête
| Champ | Type | Requis | Description |
|---|---|---|---|
| analysis | object | non | Champ data de POST /analyze — auto-chargé depuis BD si absent |
| send_email | boolean | non | Envoyer le PDF par email (défaut : true) |
Structure du PDF généré
Réponse (200)
| Champ | Type | Description |
|---|---|---|
| success | boolean | Génération réussie |
| data.pdf_size_bytes | integer | Taille du PDF en octets |
| data.pdf_generated_at | string | Horodatage ISO de génération |
| data.email_sent | boolean | Email envoyé avec succès |
| data.email_error | string|null | Message d'erreur email (si échec) |
| data.timing | object | Délais : scan_duration_s, analysis_duration_s, total_duration_s |
| data.risk_level | string | Niveau de risque (CRITICAL/HIGH/MEDIUM/LOW) |
| data.security_score | integer | Score de sécurité global (0-100) |
| data.security_grade | string | Grade (A+ → F) |
| data.findings_count | integer | Nombre de findings détectés |
| data.has_final_report | boolean | true si le rapport narratif IA a été intégré dans le PDF |
Codes de réponse
| Code | Description |
|---|---|
| 200 | PDF généré, enregistré en BD et email envoyé |
| 400 | Champ analysis absent en body ET en base de données |
| 404 | Enregistrement Recon introuvable |
| 429 | Rate limit dépassé (10 requêtes/heure) |
| 500 | Erreur génération PDF ou configuration email |
Retourne le PDF stocké en base de données pour l'enregistrement Recon spécifié.
Le PDF doit d'abord avoir été généré via POST /recon/<id>/generate_report.
Le fichier est retourné en téléchargement direct (Content-Disposition: attachment).
Paramètres URL
| Paramètre | Type | Description |
|---|---|---|
| id | integer | ID de l'enregistrement Recon |
Réponses
| Code | Description |
|---|---|
| 200 | Fichier PDF (application/pdf), nom : rapport_osint_<domain>_<id>.pdf |
| 404 | Enregistrement introuvable ou PDF pas encore généré |
Outils DNS & IP
Résolution DNS, géolocalisation IP et informations réseau
Résout tous les types d'enregistrements DNS : A, AAAA, MX, TXT, NS, CNAME, SOA, CAA. Utilise des résolveurs publics (8.8.8.8, 1.1.1.1).
Géolocalisation des IPs du domaine : pays, ville, ISP, organisation, coordonnées GPS (via ip-api.com).
Informations BGP/ASN : numéro d'AS, préfixes réseau annoncés, organisation, pays de l'AS.
Lookup DNS inverse : trouve tous les domaines hébergés sur la même adresse IP (via hackertarget.com).
Enregistrements PTR (reverse DNS) pour chaque IP résolue — identifie les serveurs par leur nom FQDN inverse.
Vérifie si les IPs du domaine sont listées dans les principales blacklists DNS (Spamhaus, Barracuda, SORBS, etc.).
Outils SSL / TLS
Analyse des certificats et de la configuration TLS
Informations du certificat SSL : sujet, émetteur, dates de validité, Subject Alt Names (SANs), algorithme de signature, numéro de série.
Configuration TLS : versions supportées (TLS 1.0–1.3), suites de chiffrement, HSTS, OCSP stapling, Perfect Forward Secrecy.
Outils Sous-domaines
Énumération passive de la surface d'attaque
OWASP Amass en mode passif — interroge des dizaines de sources OSINT, API publiques et bases de données de certificats. Résultats les plus complets.
ProjectDiscovery Subfinder — découverte rapide via crt.sh, VirusTotal, Shodan, SecurityTrails et autres sources publiques.
Assetfinder (tomnomnom) — découverte légère via Facebook CT, crt.sh, hackertarget et waybackmachine.
Requête directe sur crt.sh — extrait tous les Common Names et SANs des certificats émis pour le domaine.
github-subdomains — recherche des sous-domaines mentionnés dans les dépôts GitHub publics (nécessite GITHUB_TOKEN).
Détecte les sous-domaines vulnérables au takeover : CNAME pointant vers des services expirés (GitHub Pages, Heroku, S3, etc.).
Outils HTTP & Web
Analyse passive de la surface web
Méthodes HTTP acceptées par le serveur (GET, POST, PUT, DELETE, OPTIONS, TRACE). Détecte les méthodes dangereuses exposées.
Chaîne complète de redirections HTTP : chaque saut avec code de statut, URL destination et type de redirection (301/302).
Contenu du fichier robots.txt : directives Allow/Disallow, Sitemaps et agents. Révèle souvent des chemins sensibles.
Analyse des en-têtes de sécurité HTTP : HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy.
Détection de la stack technologique : framework web, CMS, serveur HTTP, CDN, analytics, librairies JS (via en-têtes et fingerprinting).
Détecte la présence d'un WAF (Web Application Firewall) : Cloudflare, Akamai, AWS WAF, Imperva, Sucuri, etc.
Hash MurmurHash du favicon.ico pour fingerprinting de technologies et recherche sur Shodan/Fofa.
Historique d'archivage Wayback Machine : premier snapshot, dernier snapshot, nombre total de captures (via CDX API).
Outils Email & WHOIS
Configuration email et informations d'enregistrement de domaine
Analyse complète de la sécurité email : MX records, SPF (Sender Policy Framework), DMARC, DKIM, BIMI, MTA-STS, DANE/TLSA.
Informations WHOIS structurées : registrar, dates de création/expiration/mise à jour, nameservers, statut, DNSSEC, protection de la vie privée.
Analyse IA — Groq + OpenRouter (Dual)
Double agent IA en parallèle avec fusion automatique des résultats et cache BD intelligent
Architecture d'analyse duale
Groq et OpenRouter s'exécutent en parallèle avec des prompts complémentaires. Leurs rapports sont ensuite fusionnés : findings dédupliqués, score conservatif, couverture maximale. Si aucune clé cloud n'est définie → fallback Ollama local.
llama-3.3-70b-versatile. Focalisé sur les menaces techniques : CVE actives, exploits publics, vecteurs d'attaque. 14 400 req/j gratuites. console.groq.comqwen3-235b-a22b:free. Couvre toutes les sections OSINT, documente aussi les bonnes pratiques déjà en place. Gratuit. openrouter.aiqwen3:8b (8 Go RAM). Aucune donnée sortante.Groq et OpenRouter s'exécutent simultanément via ThreadPoolExecutor. Chaque backend dispose de sa propre boucle agentique (max_search_rounds tours max). Les résultats arrivent en même temps, réduisant la durée totale.
Le merger déduplique les findings par (category, titre normalisé), prend la sévérité la plus haute en cas de doublon, unifie les strengths et immediate_actions, et calcule risk_score = max(groq, openrouter).
Chaque finding doit être ancré dans les données OSINT ET une source web vérifiée. Les deux agents font leurs propres recherches ciblées : CVE actives, standards OWASP/CIS, bonnes pratiques pour chaque technologie détectée.
L'analyse fusionnée est stockée en base liée à l'enregistrement Recon. Retour instantané jusqu'à expiration du TTL (défaut 7 jours). force_refresh: true pour forcer la régénération.
risk_score (0–100), findings avec CVE/CWE/OWASP, strengths (ce qui est bien configuré), attack_surface, immediate_actions P1/P2/P3. _merge_details pour tracer l'origine de chaque contribution.
Variables d'environnement
| Variable | Défaut | Description |
|---|---|---|
| GROQ_API_KEY | — | Clé Groq (analyste CVE/exploits). Gratuit : console.groq.com |
| ANALYSIS_MODEL | llama-3.3-70b-versatile | Modèle Groq. Alternatives : llama-3.1-8b-instant (rapide), llama3-groq-70b-8192-tool-use-preview |
| OPENROUTER_API_KEY | — | Clé OpenRouter (auditeur exhaustif + bonnes pratiques). Gratuit : openrouter.ai |
| OPENROUTER_MODEL | qwen/qwen3-235b-a22b:free | Modèle OpenRouter (235B paramètres, gratuit) |
| ANALYSIS_BACKEND_TIMEOUT | 480 | Timeout global par backend en secondes (8 min). Dépasser ce délai → le backend est ignoré dans la fusion |
| ANALYSIS_MAX_SEARCH_ROUNDS | 6 | Nombre max de cycles de recherche web par backend (chaque backend fait ses propres recherches) |
| ANALYSIS_CACHE_TTL_HOURS | 168 | Durée de validité du cache analyse en heures (168 = 7 jours). Passé ce délai, nouvelle analyse automatique. |
| ANALYSIS_LANG | fr | Langue du rapport — fr (français) ou en (anglais) |
| OLLAMA_URL | http://ollama:11434 | URL Ollama — utilisé uniquement si aucune clé cloud n'est définie (fallback) |
| TAVILY_API_KEY | — | Clé Tavily optionnelle pour des recherches web de meilleure qualité (sinon DuckDuckGo gratuit) |
Configuration recommandée (analyse duale)
# 1. Obtenir les deux clés gratuites : # Groq : https://console.groq.com/keys # OpenRouter : https://openrouter.ai/keys # 2. Ajouter dans api/.env : GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx ANALYSIS_MODEL=llama-3.3-70b-versatile OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxxx OPENROUTER_MODEL=qwen/qwen3-235b-a22b:free ANALYSIS_CACHE_TTL_HOURS=168 ANALYSIS_MAX_SEARCH_ROUNDS=6 # 3. Rebuilder le conteneur (nouvelle dépendance openai) docker-compose up -d --build api # 4. Vérifier que les deux backends sont actifs curl -u "admin@example.com:motdepasse" https://api.idachallenge.bj/analyze/status # → "dual_analysis": true, "backends_active": ["groq", "openrouter"]
Sécurité
- Authentification HTTP Basic obligatoire sur tous les endpoints IA
- Rate limiting : 5 requêtes/heure par IP sur
/analyze - Noms de modèle validés par regex stricte (
[a-zA-Z0-9._:/-], 80 chars max — inclut/pour les modèles OpenRouter) - Queries de recherche web limitées à 300 caractères
- Clés
GROQ_API_KEYetOPENROUTER_API_KEYjamais exposées dans les réponses ni les logs - Cache BD : évite les appels répétés inutiles à l'IA, réduit la consommation de tokens
Workflow complet
Du formulaire utilisateur aux résultats OSINT
Soumission du formulaire
L'utilisateur soumet son domaine et son email via POST /recon. Un OTP à 6 chiffres est envoyé par email (valable 10 min).
Vérification email
L'utilisateur valide son email via POST /verify_email avec le code OTP. L'enregistrement passe en statut pending.
Déclenchement n8n
Un webhook n8n est déclenché automatiquement. n8n appelle POST /pass_recon avec le domaine pour lancer l'analyse OSINT.
Analyse OSINT
Plus de 20 outils OSINT s'exécutent en parallèle (DNS, SSL, sous-domaines, HTTP, email, WHOIS). Les résultats sont mis en cache 24h.
Analyse IA duale
n8n appelle POST /analyze avec le JSON de /pass_recon et le recon_id. Groq et OpenRouter s'exécutent en parallèle : Groq identifie les CVE et vecteurs d'attaque, OpenRouter audite toutes les sections et documente les bonnes pratiques. Les deux rapports sont fusionnés automatiquement. Le résultat est mis en cache en BD — les appels suivants sont instantanés tant que le cache n'a pas expiré (ANALYSIS_CACHE_TTL_HOURS, défaut 7 jours).
Persistance des résultats
n8n appelle PATCH /recon/<id>/result pour enregistrer les résultats OSINT bruts et le rapport IA en base de données.
Rapport final narratif IA
n8n appelle POST /recon/<id>/generate_final_report. L'IA (Groq par défaut) condense les données OSINT + l'analyse en un rapport narratif structuré (résumé exécutif, vue infrastructure, narration des findings, recommandations priorisées). Stocké dans recon.final_report. Mis en cache — les appels suivants sont instantanés ("cached": true).
Génération du rapport PDF
n8n appelle POST /recon/<id>/generate_report. L'analyse est chargée automatiquement depuis la BD (analysis_result). Si final_report existe, son executive summary enrichit le PDF. Le PDF est enregistré en base (pdf_report BYTEA) et envoyé par email.
Téléchargement
Le rapport PDF est consultable à tout moment via GET /recon/<id>/report.pdf (authentifié). Il est stocké en base de données (pdf_report BYTEA).
Exemples cURL
Requêtes prêtes à l'emploi
1. Authentification
curl -X POST https://api.idachallenge.bj/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@example.com","password":"motdepasse"}'
2. Lancer un scan complet
curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/pass_recon \ -H "Content-Type: application/json" \ -d '{"domain":"example.com"}'
3. Scan sélectif (DNS + SSL uniquement)
curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/pass_recon \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "tools": ["dns_records", "ssl_info", "tls_config"] }'
4. Crawler une URL
curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/crawl \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "options": ["--depth", "2", "--threads", "5"] }'
5. Analyse IA duale d'un rapport OSINT (Groq + OpenRouter + cache BD)
# Vérifier les backends IA (Groq + OpenRouter) curl -u "admin@example.com:motdepasse" \ https://api.idachallenge.bj/analyze/status # → "dual_analysis": true, "backends_active": ["groq", "openrouter"] # Première analyse — Groq + OpenRouter en parallèle, fusion, sauvegarde cache BD curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/analyze \ -H "Content-Type: application/json" \ -d '{ "recon_json": { /* JSON retourné par /pass_recon */ }, "recon_id": 42, "max_search_rounds": 6 }' # → "model_used": "groq+openrouter (merged)", "_merge_details": { ... } # Appel suivant (dans les 7 jours) → retour instantané depuis le cache curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/analyze \ -H "Content-Type: application/json" \ -d '{ "recon_json": {...}, "recon_id": 42 }' # → "cached": true, "_cache": { "expires_in_h": 143.2 } # Forcer une nouvelle analyse (ignorer le cache) curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/analyze \ -H "Content-Type: application/json" \ -d '{ "recon_json": {...}, "recon_id": 42, "force_refresh": true }'
6. Générer le rapport final narratif IA
# Condensation IA (OSINT + analyse) → rapport narratif stocké dans recon.final_report curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/recon/42/generate_final_report \ -H "Content-Type: application/json" \ -d '{ "force_regenerate": false }' # → "cached": false, "data": { "executive_summary": "...", "prioritized_recommendations": [...], ... } # Appel suivant → retour instantané depuis le cache # → "cached": true
7. Générer et envoyer le rapport PDF
# Génération PDF — analysis chargé automatiquement depuis la BD curl -u "admin@example.com:motdepasse" \ -X POST https://api.idachallenge.bj/recon/42/generate_report \ -H "Content-Type: application/json" \ -d '{ "send_email": true }' # → "has_final_report": true, "security_score": 72, "security_grade": "C+"
8. Télécharger le rapport PDF
# Télécharger le PDF généré pour le recon ID 42 curl -u "admin@example.com:motdepasse" \ https://api.idachallenge.bj/recon/42/report.pdf \ -o rapport_osint.pdf
9. Consulter les logs d'audit
curl -u "admin@example.com:motdepasse" \
https://api.idachallenge.bj/logs?page=1&per_page=50