API-first · MSP & agences web
Créez et suivez des audits de conformité (Loi 25 / CAI, PIPEDA, RGPD) par programmation — et intégrez les résultats structurés dans vos propres outils.
results.json déterministe (score, violations, transferts).Les objets que vous manipulez via l'API.
Jeton sk_soleo_… généré depuis le dashboard. Agit avec les permissions et le périmètre multi-organisations de son propriétaire.
Une cible à auditer (un domaine + un client). Identifiée par un mission_id qui sert de fil conducteur à toutes les étapes.
Logiciel de capture téléchargeable, lié à la mission par un token. Il s'exécute sur le poste depuis lequel vous auditez.
L2 = trafic réseau (requêtes, tiers, cookies). L3 = événements runtime (stockage, DOM, moment du consentement).
Sortie structurée déterministe : score, violations, cross_border, summary. Le cœur de l'intégration. Indicatif : validez avant de présenter les conclusions à un client ou un tiers.
Livrable client brandé SoleoDigital, généré à partir de la capture et récupérable via l'API.
Votre premier audit, du token au rapport, en 5 minutes.
curl installé (ou un outil comme Postman)curl https://app.soleodigital.ca/api/v1/public/v1/whoami \
-H "X-API-Key: sk_soleo_votre_cle_ici"
{
"authenticated": true,
"user": "vous@agence.ca",
"organization_id": "org-123",
"key_name": "Agence Web X",
"scopes": ["audits:read", "audits:write"],
"api_base": "https://app.soleodigital.ca/api/v1/public/v1"
}
"authenticated": true, votre clé est valide. Sinon, vérifiez l'en-tête X-API-Key.curl -X POST https://app.soleodigital.ca/api/v1/public/v1/audits \
-H "X-API-Key: sk_soleo_votre_cle_ici" -H "Content-Type: application/json" \
-d '{"domain":"bnc.ca","name":"Audit BNC"}'
{
"mission_id": "mission-ab12cd34ef56",
"domain": "bnc.ca",
"name": "Audit BNC",
"status": "Prête",
"capture_status": "token_issued",
"score": null,
"agent_token": "eyJhbGci...",
"agent_token_expires_at": "2026-07-03T04:00:00+00:00",
"kit_download_url": "https://app.soleodigital.ca/api/v1/audit-missions/agent-kit?platform=windows&mission_id=mission-ab12cd34ef56",
"results_url": "https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/results.json",
"report_pdf_url": "https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/report.pdf"
}
mission_id — il sert pour toutes les étapes suivantes./api/v1/public/v1 (auth X-API-Key). En revanche kit_download_url pointe volontairement vers /api/v1/audit-missions/agent-kit : c'est le téléchargement du kit, authentifié par le token agent embarqué (pas par votre clé). Utilisez chaque URL telle qu'elle est renvoyée par l'API — ne reconstruisez pas les chemins à la main.kit_download_url dans votre navigateur (ou curl -O).bnc.ca dans l'exemple).curl https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56 \
-H "X-API-Key: sk_soleo_votre_cle_ici"
Surveillez le champ capture_status. Les principaux états :
| capture_status | Signification |
|---|---|
token_issued | Mission créée, kit prêt — en attente de la capture. |
capture_running | Des événements arrivent : la capture est en cours. |
capture_completed | Capture terminée, finalisation du dossier en cours. |
report_ready | Rapport et résultats structurés prêts à récupérer. |
results.json et attendez "ready": true. Un intervalle de 5 s est recommandé.curl https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/results.json \
-H "X-API-Key: sk_soleo_votre_cle_ici"
{
"mission_id": "mission-ab12cd34ef56",
"domain": "bnc.ca",
"ready": true,
"score": 62,
"summary": {
"post_refusal_tracking_total": 3,
"pre_consent_tracking_total": 5
},
"violations": [ ... ],
"cross_border": [ ... ],
"interpretation": {
"evidence_run_id": "run-7f3a9c",
"target_domains": ["bnc.ca"],
"executive_summary_fr": "Capture de 214 requêtes — 3 trackers actifs après refus du consentement.",
"narrative_fr": "…",
"archived": true
},
"stats": {
"total": 214,
"l2_network": 187,
"runtime_captures": 27,
"tracking_discovery": 12,
"storage_total": 41
},
"archived_at": "2026-07-02T20:15:00+00:00",
"report_pdf_url": "https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/report.pdf"
}
curl -o rapport_bnc.pdf \
https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/report.pdf \
-H "X-API-Key: sk_soleo_votre_cle_ici"
results.json renvoie "ready": false et le PDF n'est pas encore disponible.Vous venez de lancer votre premier audit automatisé avec SoleoDigital. 🎉
Prochaines étapes :
Analyse web instantanée d'un domaine — sans SoleoDigital Capture, sans capture locale. Idéal prospection & enrichissement CRM.
Contrairement à un audit complet (capture L2/L3 sur le poste du client), le Quick Scan est server-side et synchrone : il renvoie en quelques secondes les technologies détectées, le DNS, le SSL, des signaux de risque et un score. Chaque scan est enregistré dans un graphe de relations : vous pouvez ensuite lister les domaines qui partagent une même IP, un même identifiant Google Tag Manager, un même émetteur SSL, etc.
curl -X POST https://app.soleodigital.ca/api/v1/public/v1/quick-scan \
-H "X-API-Key: sk_soleo_votre_cle_ici" -H "Content-Type: application/json" \
-d '{"domain":"exemple.com"}'
{
"domain": "exemple.com",
"reachable": true,
"http_status": 200,
"https": true,
"risk_score": 30,
"grade": "B",
"categories": {
"Framework": ["Next.js", "React"],
"Analytics": ["Matomo"],
"Server": ["Apache"]
},
"dns": { "a": ["51.161.122.78"], "asn": "AS16276", "ns": ["ns10.ovh.ca"] },
"ssl": { "issuer": "Let's Encrypt", "days_remaining": 64 },
"domain_age": { "registered_at": "2018-04-12T00:00:00+00:00", "age_days": 2973, "registrar": "OVH sas" },
"risk_signals": [
{ "code": "missing_csp", "label": "Content-Security-Policy absente", "weight": 6 },
{ "code": "no_cmp", "label": "Trackers sans plateforme de consentement (CMP)", "weight": 10 }
],
"cached": false,
"entities": {
"ip": ["51.161.122.78"], "asn": ["AS16276"],
"gtm_ids": [], "ga_ids": [], "ssl_issuer": "Let's Encrypt",
"third_party_hosts": ["calendly.com", "plausible.io"]
}
}
grade va de A (faible risque) à F. Le scan est enregistré dans le graphe et, si un webhook domain.scanned est configuré, une notification est envoyée à votre CRM.curl https://app.soleodigital.ca/api/v1/public/v1/domains/exemple.com/connections \
-H "X-API-Key: sk_soleo_votre_cle_ici"
{
"domain": "exemple.com",
"scanned": true,
"related_domains_count": 7,
"by_signal": { "strong": 1, "medium": 2, "provider": 1 },
"connections": [
{
"etype": "gtm_id", "value": "GTM-AAA111", "signal": "strong",
"count": 1, "shared_with": [{ "domain": "autre-site.com", "grade": "C" }]
},
{
"etype": "ip", "value": "51.161.122.78", "signal": "medium",
"count": 2, "shared_with": [ ... ]
}
]
}
Chaque connexion porte un signal qui indique la force du lien :
| signal | Signification | Types d'entités |
|---|---|---|
strong | Quasi-preuve de même propriétaire | GTM, Google Analytics, Google Ads, Meta Pixel, Matomo |
medium | Lien probable | IP partagée, hôte tiers peu commun |
provider | Partage d'infrastructure | Name server, émetteur SSL, ASN |
Le modèle d'exécution, de l'appel API au rapport.
POST /audits crée une mission et émet un token à courte durée de vie + un lien de téléchargement SoleoDigital Capture.results.json déterministe et un rapport PDF brandé sont produits, puis récupérables par l'API.Conventions transverses : auth, pagination, polling, erreurs.
Chaque requête porte votre clé dans l'en-tête X-API-Key. Portées disponibles : audits:read, audits:write, mia_fast:read, mia_fast:write.
curl https://app.soleodigital.ca/api/v1/public/v1/whoami \
-H "X-API-Key: sk_soleo_votre_cle_ici"
Créez une clé sandbox dans le dashboard (Intégrations / API → case « Clé sandbox »). Les audits créés avec cette clé sont simulés : results.json est disponible immédiatement, aucun SoleoDigital Capture réel ni consommation de quota.
curl -X POST https://app.soleodigital.ca/api/v1/public/v1/audits \
-H "X-API-Key: sk_soleo_sandbox_..." -H "Content-Type: application/json" \
-d '{"domain":"exemple.ca","name":"Test intégration"}'
La réponse inclut "sandbox": true et "ready": true. Le PDF n'est pas généré en sandbox — utilisez results.json.
Idempotency-Key)Sur POST /audits, envoyez un en-tête Idempotency-Key unique (8–255 caractères). En cas de timeout ou retry, la même clé + le même corps renvoient la réponse originale (TTL 24 h). Un corps différent avec la même clé → 409 Conflict.
curl -X POST https://app.soleodigital.ca/api/v1/public/v1/audits \
-H "X-API-Key: sk_soleo_..." \
-H "Idempotency-Key: crm-deal-88421-v1" \
-H "Content-Type: application/json" \
-d '{"domain":"client.ca","name":"Audit CRM"}'
GET /audits est paginé via ?limit= (1–500, défaut 50) et ?offset=. La réponse renvoie total, limit, offset et items.
curl "https://app.soleodigital.ca/api/v1/public/v1/audits?limit=50&offset=0" \
-H "X-API-Key: sk_soleo_votre_cle_ici"
Polling des résultats (limite molle). Après le lancement du kit, interrogez results.json jusqu'à "ready": true. Intervalle recommandé : 5 s ; évitez de dépasser 1 req/s par mission. C'est une consigne d'usage, pas un rejet automatique.
Quick Scan (limite dure). POST /quick-scan est plafonné à 15 scans/minute par clé. Au-delà, l'API renvoie 429 avec un en-tête Retry-After (en secondes) — respectez-le avant de réessayer.
Les erreurs suivent le format { "detail": "message" } avec un code HTTP standard (voir codes d'erreur). Traitez notamment 402 (quota atteint), 401 (clé invalide) et 429 (débit Quick Scan dépassé — attendez Retry-After).
Deux façons de brancher SoleoDigital à votre CRM (HubSpot, Salesforce, Zapier, Make…).
Le plus simple : après avoir créé un audit, votre CRM interroge results.json jusqu'à "ready": true, puis récupère le score et le PDF. Aucune configuration côté SoleoDigital. Idéal pour un premier branchement ou un CRM sans endpoint public.
Configurez un webhook dans le dashboard → Intégrations / API → Webhooks. Dès qu'un audit est finalisé, SoleoDigital envoie un POST signé vers votre URL — pas de polling. C'est ce qu'attendent Zapier, Make et les workflows CRM.
audit.completed){
"event": "audit.completed",
"created_at": "2026-07-02T20:15:00+00:00",
"data": {
"mission_id": "mission-ab12cd34ef56",
"domain": "bnc.ca",
"organization": "Client Final",
"capture_status": "report_ready",
"score": 62,
"violations_count": 4,
"violations_high": 1,
"post_refusal_tracking_total": 2,
"results_url": "https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/results.json",
"report_pdf_url": "https://app.soleodigital.ca/api/v1/public/v1/audits/mission-ab12cd34ef56/report.pdf",
"report_html_url": "https://app.soleodigital.ca/api/v1/live-capture/demo-report?stem=m-mission-ab12cd34ef56",
"report_html_download_url": "https://app.soleodigital.ca/api/v1/live-capture/demo-report/download?stem=m-mission-ab12cd34ef56",
"dashboard_url": "https://app.soleodigital.ca/index.html#mission-mission-ab12cd34ef56"
}
}
Content-Type: application/json
X-Soleo-Event: audit.completed
X-Soleo-Delivery: <identifiant unique de livraison>
X-Soleo-Signature: sha256=<HMAC-SHA256 du corps avec votre secret>
secret du webhook, et comparez à X-Soleo-Signature.import hmac, hashlib
def verifie(corps: bytes, entete_signature: str, secret: str) -> bool:
attendu = "sha256=" + hmac.new(secret.encode(), corps, hashlib.sha256).hexdigest()
return hmac.compare_digest(attendu, entete_signature)
Répondez avec un code 2xx pour accuser réception. En cas d'échec réseau ou 5xx, SoleoDigital retente automatiquement (jusqu'à 5 tentatives, backoff exponentiel ~2 s → 45 s). Une réponse 4xx est considérée définitive (pas de retry). La livraison est asynchrone : elle ne bloque jamais l'audit. Toutes les tentatives sont visibles côté Super Admin.
| event | Déclencheur | Charge utile principale |
|---|---|---|
audit.completed | Un audit est finalisé (rapport prêt) | mission_id, domain, score, violations_count, violations_high, results_url, report_pdf_url, report_html_url |
audit.score_dropped | Le score de conformité baisse significativement | previous_score, current_score, delta, violations_count, report_pdf_url, report_html_url |
domain.scanned | Un domaine est analysé par le Quick Scan | domain, risk_score, grade, technologies, related_domains_count, connections_url |
mia_fast.completed | Scan MIA Fast prospection terminé (~17 s, signaux serveur) | job_id, domain, reference_id, risk_score, tier, cmp_detected, sales_play_id, recommended_sales_action_fr, report_pdf_url |
domain.scanned){
"event": "domain.scanned",
"created_at": "2026-07-03T05:20:00+00:00",
"data": {
"domain": "exemple.com",
"reachable": true,
"risk_score": 30,
"grade": "B",
"technologies": ["Next.js", "React", "Apache", "Matomo"],
"related_domains_count": 7,
"ip": ["51.161.122.78"],
"asn": "AS16276",
"ssl_issuer": "Let's Encrypt",
"connections_url": "https://app.soleodigital.ca/api/v1/public/v1/domains/exemple.com/connections"
}
}
risk_score et related_domains_count pour prioriser vos relances et recommander un audit complet. Les en-têtes et la vérification de signature sont identiques à audit.completed (seul X-Soleo-Event change).Chaque requête porte votre clé dans l'en-tête X-API-Key. Portées : audits:read, audits:write. La clé agit avec les permissions et le cloisonnement multi-organisations de son propriétaire.
Base : https://app.soleodigital.ca/api/v1/public/v1
En-tête : X-API-Key: sk_soleo_xxxxxxxxxxxxxxxx
| Champ | Type | Défaut | Description |
|---|---|---|---|
domain | string | — | Domaine à auditer (obligatoire) |
name | string | Audit <domaine> | Nom de la mission |
organization | string | votre org | Nom du client final |
expires_in_days | int | 30 | Validité de la mission (1–365) |
authorized | bool | true | Autoriser la capture immédiatement |
with_agent | bool | true | Générer token agent + lien kit |
agent_token_hours | int | 8 | Validité du token agent (1–24) |
Liste paginée des audits accessibles (?limit=50&offset=0) ou état d'un audit précis. Réponse : mission_id, domain, status, capture_status, score, results_url, report_pdf_url…
Résultats structurés une fois la capture finalisée : ready, score, summary, violations, cross_border, interpretation, stats. Renvoie "ready": false tant que la capture n'est pas terminée.
Rapport PDF brandé SoleoDigital, prêt à livrer à votre client.
Analyse web instantanée d'un domaine (server-side, sans SoleoDigital Capture). Portée requise : audits:read.
| Champ | Type | Défaut | Description |
|---|---|---|---|
domain | string | — | Domaine à analyser (obligatoire) |
persist | bool | true | Enregistrer le résultat dans le graphe de relations |
force | bool | false | Ignorer le cache et forcer un nouveau scan live |
Réponse : domain, reachable, http_status, https, risk_score, grade, categories, technologies, dns, ssl, domain_age, security_headers, risk_signals, entities, cached.
"cached": true) sans re-scanner le site cible ni renvoyer de webhook domain.scanned. Passez "force": true pour forcer un scan frais.Domaines liés au domaine donné, groupés par entité partagée (IP, ASN, name server, émetteur SSL, GTM/GA/Ads/Pixel, Matomo, hôte tiers). Portée requise : audits:read. Cloisonné à votre périmètre d'organisation.
Réponse : domain, scanned, related_domains_count, by_signal, connections[] { etype, value, signal, count, shared_with[] }.
| Code | Signification |
|---|---|
400 | Requête invalide (ex. domaine mal formé) |
401 | Clé API manquante ou invalide |
403 | Portée insuffisante ou permission manquante |
402 | Quota de missions du plan atteint |
404 | Audit introuvable (ou hors de votre périmètre) |
429 | Trop de requêtes (limite Quick Scan). En-tête Retry-After renvoyé. |
504 | Le Quick Scan a dépassé le délai (site cible trop lent) |
Besoin d'aide ? contact@soleodigital.ca